The following makes sure to discover the scalar loop IV exit during analysis as failure to do so (if DCE and friends are disabled this can happen due to if-conversion doing DCE and FRE on the if-converted loop) would ICE later.
I refrained from larger refactoring to be able to eventually backport. Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/116982 * tree-vectorizer.h (vect_analyze_loop): Pass in .LOOP_VECTORIZED call. (vect_analyze_loop_form): Likewise. * tree-vect-loop.cc (vect_analyze_loop_form): Reject loops where we cannot determine a IV exit for the scalar loop. (vect_analyze_loop): Adjust. * tree-vectorizer.cc (try_vectorize_loop_1): Likewise. * tree-parloops.cc (gather_scalar_reductions): Likewise. --- gcc/tree-parloops.cc | 4 ++-- gcc/tree-vect-loop.cc | 23 +++++++++++++++++++---- gcc/tree-vectorizer.cc | 3 ++- gcc/tree-vectorizer.h | 6 ++++-- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/gcc/tree-parloops.cc b/gcc/tree-parloops.cc index f4468658732..6a1249bebb6 100644 --- a/gcc/tree-parloops.cc +++ b/gcc/tree-parloops.cc @@ -3305,7 +3305,7 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list vec_info_shared shared; vect_loop_form_info info; - if (!vect_analyze_loop_form (loop, &info)) + if (!vect_analyze_loop_form (loop, NULL, &info)) goto gather_done; simple_loop_info = vect_create_loop_vinfo (loop, &shared, &info); @@ -3347,7 +3347,7 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list { vec_info_shared shared; vect_loop_form_info info; - if (vect_analyze_loop_form (loop->inner, &info)) + if (vect_analyze_loop_form (loop->inner, NULL, &info)) { simple_loop_info = vect_create_loop_vinfo (loop->inner, &shared, &info); diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index f5ecf0bdb80..2335642d67c 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -1737,7 +1737,8 @@ vect_compute_single_scalar_iteration_cost (loop_vec_info loop_vinfo) niter could be analyzed under some assumptions. */ opt_result -vect_analyze_loop_form (class loop *loop, vect_loop_form_info *info) +vect_analyze_loop_form (class loop *loop, gimple *loop_vectorized_call, + vect_loop_form_info *info) { DUMP_VECT_SCOPE ("vect_analyze_loop_form"); @@ -1747,6 +1748,18 @@ vect_analyze_loop_form (class loop *loop, vect_loop_form_info *info) "not vectorized:" " could not determine main exit from" " loop with multiple exits.\n"); + if (loop_vectorized_call) + { + tree arg = gimple_call_arg (loop_vectorized_call, 1); + class loop *scalar_loop = get_loop (cfun, tree_to_shwi (arg)); + edge scalar_exit_e = vec_init_loop_exit_info (scalar_loop); + if (!scalar_exit_e) + return opt_result::failure_at (vect_location, + "not vectorized:" + " could not determine main exit from" + " loop with multiple exits.\n"); + } + info->loop_exit = exit_e; if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, @@ -1819,7 +1832,7 @@ vect_analyze_loop_form (class loop *loop, vect_loop_form_info *info) /* Analyze the inner-loop. */ vect_loop_form_info inner; - opt_result res = vect_analyze_loop_form (loop->inner, &inner); + opt_result res = vect_analyze_loop_form (loop->inner, NULL, &inner); if (!res) { if (dump_enabled_p ()) @@ -3520,7 +3533,8 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared, for it. The different analyses will record information in the loop_vec_info struct. */ opt_loop_vec_info -vect_analyze_loop (class loop *loop, vec_info_shared *shared) +vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call, + vec_info_shared *shared) { DUMP_VECT_SCOPE ("analyze_loop_nest"); @@ -3538,7 +3552,8 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared) /* Analyze the loop form. */ vect_loop_form_info loop_form_info; - opt_result res = vect_analyze_loop_form (loop, &loop_form_info); + opt_result res = vect_analyze_loop_form (loop, loop_vectorized_call, + &loop_form_info); if (!res) { if (dump_enabled_p ()) diff --git a/gcc/tree-vectorizer.cc b/gcc/tree-vectorizer.cc index d4ab47349a3..fed12c41f9c 100644 --- a/gcc/tree-vectorizer.cc +++ b/gcc/tree-vectorizer.cc @@ -1067,7 +1067,8 @@ try_vectorize_loop_1 (hash_table<simduid_to_vf> *&simduid_to_vf_htab, LOCATION_LINE (vect_location.get_location_t ())); /* Try to analyze the loop, retaining an opt_problem if dump_enabled_p. */ - opt_loop_vec_info loop_vinfo = vect_analyze_loop (loop, &shared); + opt_loop_vec_info loop_vinfo = vect_analyze_loop (loop, loop_vectorized_call, + &shared); loop->aux = loop_vinfo; if (!loop_vinfo) diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 490061aea2f..73bccb5a40a 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -2460,7 +2460,8 @@ extern bool check_reduction_path (dump_user_location_t, loop_p, gphi *, tree, enum tree_code); extern bool needs_fold_left_reduction_p (tree, code_helper); /* Drive for loop analysis stage. */ -extern opt_loop_vec_info vect_analyze_loop (class loop *, vec_info_shared *); +extern opt_loop_vec_info vect_analyze_loop (class loop *, gimple *, + vec_info_shared *); extern tree vect_build_loop_niters (loop_vec_info, bool * = NULL); extern void vect_gen_vector_loop_niters (loop_vec_info, tree, tree *, tree *, bool); @@ -2495,7 +2496,8 @@ struct vect_loop_form_info gcond *inner_loop_cond; edge loop_exit; }; -extern opt_result vect_analyze_loop_form (class loop *, vect_loop_form_info *); +extern opt_result vect_analyze_loop_form (class loop *, gimple *, + vect_loop_form_info *); extern loop_vec_info vect_create_loop_vinfo (class loop *, vec_info_shared *, const vect_loop_form_info *, loop_vec_info = nullptr); -- 2.43.0