]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/120089 - force all PHIs live for early-break vect
authorRichard Biener <rguenther@suse.de>
Mon, 5 May 2025 12:29:34 +0000 (14:29 +0200)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 8 May 2025 06:36:53 +0000 (08:36 +0200)
The following makes sure to even mark unsupported PHIs live when
doing early-break vectorization since otherwise we fail to validate
we can vectorize those and generate wrong code based on the scalar
PHIs which would only work with a vectorization factor of one.

PR tree-optimization/120089
* tree-vect-stmts.cc (vect_stmt_relevant_p): Mark all
PHIs live when not already so and doing early-break
vectorization.
(vect_mark_stmts_to_be_vectorized): Skip virtual PHIs.
* tree-vect-slp.cc (vect_analyze_slp): Robustify handling
of early-break forced IVs.

* gcc.dg/vect/vect-early-break_134-pr120089.c: New testcase.

gcc/testsuite/gcc.dg/vect/vect-early-break_134-pr120089.c [new file with mode: 0644]
gcc/tree-vect-slp.cc
gcc/tree-vect-stmts.cc

diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_134-pr120089.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_134-pr120089.c
new file mode 100644 (file)
index 0000000..4d8199c
--- /dev/null
@@ -0,0 +1,66 @@
+/* { dg-add-options vect_early_break } */
+/* { dg-additional-options "-funswitch-loops" } */
+
+#include "tree-vect.h"
+
+typedef int type;
+typedef type Vec2[2];
+
+struct BytesVec {
+    type d[100];
+};
+
+__attribute__((noipa)) struct BytesVec
+buildVertexBufferData(const Vec2 *origVertices, bool needsZW,
+                      unsigned paddingSize, unsigned long t) {
+    const unsigned vertexCount = t;
+    struct BytesVec data = (struct BytesVec){.d = {0}};
+    type *nextVertexPtr = data.d;
+
+    for (unsigned vertexIdx = 0u; vertexIdx < vertexCount; ++vertexIdx) {
+
+        if (vertexIdx > t)
+            __builtin_trap();
+        __builtin_memcpy(nextVertexPtr, &origVertices[vertexIdx],
+                         2 * sizeof(type));
+        nextVertexPtr += 2;
+
+        if (needsZW) {
+            nextVertexPtr += 2;
+        }
+
+        nextVertexPtr += paddingSize;
+    }
+
+    return data;
+}
+Vec2 origVertices[] = {
+    {0, 1}, {2, 3}, {4, 5}, {6, 7},
+    {8, 9}, {10, 11}, {12, 13}, {14, 15},
+    {16, 17}, {18, 19}, {20, 21}, {22, 23},
+    {24, 25}, {26, 27}, {27, 28}, {29, 30},
+};
+
+int main()
+{
+  check_vect ();
+  struct BytesVec vec
+    = buildVertexBufferData(origVertices, false, 0,
+                           sizeof(origVertices) / sizeof(origVertices[0]));
+
+  int errors = 0;
+  for (unsigned i = 0; i < 100; i++) {
+      if (i / 2 < sizeof(origVertices) / sizeof(origVertices[0])) {
+         int ii = i;
+         int e = origVertices[ii / 2][ii % 2];
+         if (vec.d[i] != e)
+           errors++;
+      } else {
+         if (vec.d[i] != 0)
+           errors++;
+      }
+  }
+  if (errors)
+    __builtin_abort();
+  return 0;
+}
index 562e2227c7c490c12df266625f7dd5d20d41a176..80e9c010b1a10bb554dd34043511502543d6e1c6 100644 (file)
@@ -5042,14 +5042,17 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
            vec<stmt_vec_info> roots = vNULL;
            vec<tree> remain = vNULL;
            gphi *phi = as_a<gphi *> (STMT_VINFO_STMT (stmt_info));
-           stmts.create (1);
            tree def = gimple_phi_arg_def_from_edge (phi, latch_e);
            stmt_vec_info lc_info = loop_vinfo->lookup_def (def);
-           stmts.quick_push (vect_stmt_to_vectorize (lc_info));
-           vect_build_slp_instance (vinfo, slp_inst_kind_reduc_group,
-                                    stmts, roots, remain,
-                                    max_tree_size, &limit,
-                                    bst_map, NULL, force_single_lane);
+           if (lc_info)
+             {
+               stmts.create (1);
+               stmts.quick_push (vect_stmt_to_vectorize (lc_info));
+               vect_build_slp_instance (vinfo, slp_inst_kind_reduc_group,
+                                        stmts, roots, remain,
+                                        max_tree_size, &limit,
+                                        bst_map, NULL, force_single_lane);
+             }
            /* When the latch def is from a different cycle this can only
               be a induction.  Build a simple instance for this.
               ???  We should be able to start discovery from the PHI
@@ -5059,8 +5062,6 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
            tem.quick_push (stmt_info);
            if (!bst_map->get (tem))
              {
-               gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info)
-                           == vect_induction_def);
                stmts.create (1);
                stmts.quick_push (stmt_info);
                vect_build_slp_instance (vinfo, slp_inst_kind_reduc_group,
index ea0b42627815a562540e3ae7cc652c2b38d0ceb6..af7114d419238c10767870e2113a6f1911bed323 100644 (file)
@@ -419,18 +419,21 @@ vect_stmt_relevant_p (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
        }
     }
 
-  /* Check if it's an induction and multiple exits.  In this case there will be
-     a usage later on after peeling which is needed for the alternate exit.  */
+  /* Check if it's a not live PHI and multiple exits.  In this case
+     there will be a usage later on after peeling which is needed for the
+     alternate exit.  */
   if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo)
-      && STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def)
+      && is_a <gphi *> (stmt)
+      && ((! VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))
+         && ! *live_p)
+         || STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def))
     {
       if (dump_enabled_p ())
-         dump_printf_loc (MSG_NOTE, vect_location,
-                          "vec_stmt_relevant_p: induction forced for "
-                          "early break.\n");
+       dump_printf_loc (MSG_NOTE, vect_location,
+                        "vec_stmt_relevant_p: PHI forced live for "
+                        "early break.\n");
       LOOP_VINFO_EARLY_BREAKS_LIVE_IVS (loop_vinfo).safe_push (stmt_info);
       *live_p = true;
-
     }
 
   if (*live_p && *relevant == vect_unused_in_scope
@@ -714,6 +717,8 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo, bool *fatal)
       bb = bbs[i];
       for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
        {
+         if (virtual_operand_p (gimple_phi_result (gsi_stmt (si))))
+           continue;
          stmt_vec_info phi_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
          if (dump_enabled_p ())
            dump_printf_loc (MSG_NOTE, vect_location, "init: phi relevant? %G",