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

Reply via email to