Restructure vect_analyze_loop
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 6 Nov 2019 12:29:27 +0000 (12:29 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 6 Nov 2019 12:29:27 +0000 (12:29 +0000)
Once vect_analyze_loop has found a valid loop_vec_info X, we carry
on searching for alternatives if (1) X doesn't satisfy simdlen or
(2) we want to vectorize the epilogue of X.  I have a patch that
optionally adds a third reason: we want to see if there are cheaper
alternatives to X.

This patch restructures vect_analyze_loop so that it's easier
to add more reasons for continuing.  There's supposed to be no
behavioural change.

If we wanted to, we could allow vectorisation of epilogues once
loop->simdlen has been reached by changing "loop->simdlen" to
"simdlen" in the new vect_epilogues condition.  That should be
a separate change though.

2019-11-06  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* tree-vect-loop.c (vect_analyze_loop): Break out of the main
loop when we've finished, rather than returning directly from
the loop.  Use a local variable to track whether we're still
searching for the preferred simdlen.  Make vect_epilogues
record whether the next iteration should try to treat the
loop as an epilogue.

From-SVN: r277879

gcc/ChangeLog
gcc/tree-vect-loop.c

index 6c33a80cec7761d4b297cf07eac81a201ea15ed4..a8a8968c9bc3c81df8f293ed63cf2c169113757e 100644 (file)
@@ -1,3 +1,12 @@
+2019-11-06  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * tree-vect-loop.c (vect_analyze_loop): Break out of the main
+       loop when we've finished, rather than returning directly from
+       the loop.  Use a local variable to track whether we're still
+       searching for the preferred simdlen.  Make vect_epilogues
+       record whether the next iteration should try to treat the
+       loop as an epilogue.
+
 2019-11-06  Vineet Gupta  <vgupta@synopsys.com>
 
        * config/arc/arc-c.c (arc_cpu_cpp_builtins) : Add
index a63f8d51cc454fcbbd6b223639a105089389d27f..f8049047a8e3818cc1ff52e6e1ca6adfc3d2af91 100644 (file)
@@ -2382,16 +2382,13 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
   poly_uint64 lowest_th = 0;
   unsigned vectorized_loops = 0;
 
-  /* Only vectorize epilogues if PARAM_VECT_EPILOGUES_NOMASK is enabled, this
-     is not a simd loop and it is the most inner loop.  */
-  bool vect_epilogues
-    = !loop->simdlen && loop->inner == NULL
-      && PARAM_VALUE (PARAM_VECT_EPILOGUES_NOMASK);
+  bool vect_epilogues = false;
+  opt_result res = opt_result::success ();
+  unsigned HOST_WIDE_INT simdlen = loop->simdlen;
   while (1)
     {
       /* Check the CFG characteristics of the loop (nesting, entry/exit).  */
-      opt_loop_vec_info loop_vinfo
-       = vect_analyze_loop_form (loop, shared);
+      opt_loop_vec_info loop_vinfo = vect_analyze_loop_form (loop, shared);
       if (!loop_vinfo)
        {
          if (dump_enabled_p ())
@@ -2404,67 +2401,70 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
 
       bool fatal = false;
 
-      if (vect_epilogues && first_loop_vinfo)
+      if (vect_epilogues)
        LOOP_VINFO_ORIG_LOOP_INFO (loop_vinfo) = first_loop_vinfo;
 
-      opt_result res = vect_analyze_loop_2 (loop_vinfo, fatal, &n_stmts);
+      res = vect_analyze_loop_2 (loop_vinfo, fatal, &n_stmts);
       if (next_size == 0)
        autodetected_vector_size = loop_vinfo->vector_size;
 
+      loop->aux = NULL;
       if (res)
        {
          LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
          vectorized_loops++;
 
-         if ((loop->simdlen
-              && maybe_ne (LOOP_VINFO_VECT_FACTOR (loop_vinfo),
-                           (unsigned HOST_WIDE_INT) loop->simdlen))
-             || vect_epilogues)
+         /* Once we hit the desired simdlen for the first time,
+            discard any previous attempts.  */
+         if (simdlen
+             && known_eq (LOOP_VINFO_VECT_FACTOR (loop_vinfo), simdlen))
            {
-             if (first_loop_vinfo == NULL)
-               {
-                 first_loop_vinfo = loop_vinfo;
-                 lowest_th
-                   = LOOP_VINFO_VERSIONING_THRESHOLD (first_loop_vinfo);
-                 loop->aux = NULL;
-               }
-             else
-               {
-                 /* Keep track of vector sizes that we know we can vectorize
-                    the epilogue with.  Only vectorize first epilogue.  */
-                 if (vect_epilogues
-                     && first_loop_vinfo->epilogue_vinfos.is_empty ())
-                   {
-                     loop->aux = NULL;
-                     first_loop_vinfo->epilogue_vinfos.reserve (1);
-                     first_loop_vinfo->epilogue_vinfos.quick_push (loop_vinfo);
-                     LOOP_VINFO_ORIG_LOOP_INFO (loop_vinfo) = first_loop_vinfo;
-                     poly_uint64 th
-                       = LOOP_VINFO_VERSIONING_THRESHOLD (loop_vinfo);
-                     gcc_assert (!LOOP_REQUIRES_VERSIONING (loop_vinfo)
-                                 || maybe_ne (lowest_th, 0U));
-                     /* Keep track of the known smallest versioning
-                        threshold.  */
-                     if (ordered_p (lowest_th, th))
-                       lowest_th = ordered_min (lowest_th, th);
-                   }
-                 else
-                   delete loop_vinfo;
-               }
+             delete first_loop_vinfo;
+             first_loop_vinfo = opt_loop_vec_info::success (NULL);
+             LOOP_VINFO_ORIG_LOOP_INFO (loop_vinfo) = NULL;
+             simdlen = 0;
            }
-         else
+
+         if (first_loop_vinfo == NULL)
            {
-             delete first_loop_vinfo;
-             return loop_vinfo;
+             first_loop_vinfo = loop_vinfo;
+             lowest_th = LOOP_VINFO_VERSIONING_THRESHOLD (first_loop_vinfo);
+           }
+         else if (vect_epilogues)
+           {
+             first_loop_vinfo->epilogue_vinfos.safe_push (loop_vinfo);
+             poly_uint64 th = LOOP_VINFO_VERSIONING_THRESHOLD (loop_vinfo);
+             gcc_assert (!LOOP_REQUIRES_VERSIONING (loop_vinfo)
+                         || maybe_ne (lowest_th, 0U));
+             /* Keep track of the known smallest versioning
+                threshold.  */
+             if (ordered_p (lowest_th, th))
+               lowest_th = ordered_min (lowest_th, th);
            }
+         else
+           delete loop_vinfo;
+
+         /* Only vectorize epilogues if PARAM_VECT_EPILOGUES_NOMASK is
+            enabled, this is not a simd loop and it is the innermost loop.  */
+         vect_epilogues = (!loop->simdlen
+                           && loop->inner == NULL
+                           && PARAM_VALUE (PARAM_VECT_EPILOGUES_NOMASK)
+                           /* For now only allow one epilogue loop.  */
+                           && first_loop_vinfo->epilogue_vinfos.is_empty ());
+
+         /* Commit to first_loop_vinfo if we have no reason to try
+            alternatives.  */
+         if (!simdlen && !vect_epilogues)
+           break;
        }
       else
-       delete loop_vinfo;
-
-      if (fatal)
        {
-         gcc_checking_assert (first_loop_vinfo == NULL);
-         return opt_loop_vec_info::propagate_failure (res);
+         delete loop_vinfo;
+         if (fatal)
+           {
+             gcc_checking_assert (first_loop_vinfo == NULL);
+             break;
+           }
        }
 
       if (next_size < vector_sizes.length ()
@@ -2473,24 +2473,7 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
 
       if (next_size == vector_sizes.length ()
          || known_eq (autodetected_vector_size, 0U))
-       {
-         if (first_loop_vinfo)
-           {
-             loop->aux = (loop_vec_info) first_loop_vinfo;
-             if (dump_enabled_p ())
-               {
-                 dump_printf_loc (MSG_NOTE, vect_location,
-                                  "***** Choosing vector size ");
-                 dump_dec (MSG_NOTE, first_loop_vinfo->vector_size);
-                 dump_printf (MSG_NOTE, "\n");
-               }
-             LOOP_VINFO_VERSIONING_THRESHOLD (first_loop_vinfo) = lowest_th;
-
-             return first_loop_vinfo;
-           }
-         else
-           return opt_loop_vec_info::propagate_failure (res);
-       }
+       break;
 
       /* Try the next biggest vector size.  */
       next_vector_size = vector_sizes[next_size++];
@@ -2503,6 +2486,22 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
          dump_printf (MSG_NOTE, "\n");
        }
     }
+
+  if (first_loop_vinfo)
+    {
+      loop->aux = (loop_vec_info) first_loop_vinfo;
+      if (dump_enabled_p ())
+       {
+         dump_printf_loc (MSG_NOTE, vect_location,
+                          "***** Choosing vector size ");
+         dump_dec (MSG_NOTE, first_loop_vinfo->vector_size);
+         dump_printf (MSG_NOTE, "\n");
+       }
+      LOOP_VINFO_VERSIONING_THRESHOLD (first_loop_vinfo) = lowest_th;
+      return first_loop_vinfo;
+    }
+
+  return opt_loop_vec_info::propagate_failure (res);
 }
 
 /* Return true if there is an in-order reduction function for CODE, storing