We were not correctly verifying dominance of the vector definition
with the scalar use in case of PHI use stmts.  We have to ensure
the respective PHI edge source can reach the definition.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/126862
        * tree-vect-slp.cc (vect_bb_slp_mark_live_stmts): For PHI
        uses verify dominance to the PHI use edge source.

        * gcc.dg/vect/bb-slp-pr126862.c: New testcase.
---
 gcc/testsuite/gcc.dg/vect/bb-slp-pr126862.c | 30 +++++++++++
 gcc/tree-vect-slp.cc                        | 55 ++++++++++++---------
 2 files changed, 63 insertions(+), 22 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/bb-slp-pr126862.c

diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr126862.c 
b/gcc/testsuite/gcc.dg/vect/bb-slp-pr126862.c
new file mode 100644
index 00000000000..da54b941d79
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr126862.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+#include <stdint.h>
+static uint16_t
+(safe_mod_func_uint16_t_u_u)(uint16_t ui1, uint16_t ui2 ){
+  return
+    (ui2 == 0) ?
+    ((ui1)) :
+    (ui1 % ui2);
+}
+struct a {};
+int32_t b[4][5];
+int16_t c[5];
+uint16_t d;
+int32_t *e(struct a, uint16_t, uint32_t, int32_t *, int64_t);
+uint32_t f() {
+  int32_t g[4][5];
+  for (b[3][3] = 0; b[3][3] <= 3; b[3][3]++) {
+    struct a h;
+    e(h, 0, g[2][4], &b[3][3], b[9][4]);
+  }
+}
+int32_t *e(struct a, uint16_t, uint32_t, int32_t *k, int64_t) {
+  int32_t i[4];
+  uint16_t *j = &d;
+  if (c[4] ^= safe_mod_func_uint16_t_u_u(++*j, 0), *i)
+    *j = 0;
+  return k;
+}
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 89a67e4eb38..d6515be26d1 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -9267,32 +9267,43 @@ vect_bb_slp_mark_live_stmts (bb_vec_info bb_vinfo, 
slp_tree node,
             during code-generation, simply not replacing uses for those
             hopefully rare cases.  */
          imm_use_iterator use_iter;
-         gimple *use_stmt;
-         stmt_vec_info use_stmt_info;
 
          bool live_p = false;
          bool can_insert = true;
-         FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, DEF_FROM_PTR (def_p))
-           if (!is_gimple_debug (use_stmt)
-               && (!(use_stmt_info = bb_vinfo->lookup_stmt (use_stmt))
-                   || !PURE_SLP_STMT (use_stmt_info)))
-             {
-               live_p = true;
-               if (!last_stmt)
-                 last_stmt
-                   = (node->si ? node->si
-                      : vect_find_last_scalar_stmt_in_slp (node)->stmt);
-               if (!vect_stmt_dominates_stmt_p (last_stmt, use_stmt))
-                 {
-                   if (dump_enabled_p ())
-                     dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                                      "Cannot determine insertion place for "
-                                      "lane extract of %T at node %p\n",
-                                      DEF_FROM_PTR (def_p), (void *)node);
+         use_operand_p use_p;
+         FOR_EACH_IMM_USE_FAST (use_p, use_iter, DEF_FROM_PTR (def_p))
+           {
+             gimple *use_stmt = USE_STMT (use_p);
+             stmt_vec_info use_stmt_info;
+             if (!(!is_gimple_debug (use_stmt)
+                   && (!(use_stmt_info = bb_vinfo->lookup_stmt (use_stmt))
+                       || !PURE_SLP_STMT (use_stmt_info))))
+               continue;
+             live_p = true;
+             if (!last_stmt)
+               last_stmt
+                 = (node->si ? node->si
+                    : vect_find_last_scalar_stmt_in_slp (node)->stmt);
+             if (is_a <gphi *> (use_stmt))
+               {
+                 if (!dominated_by_p (CDI_DOMINATORS,
+                                      phi_arg_edge_from_use (use_p)->src,
+                                      gimple_bb (last_stmt)))
                    can_insert = false;
-                   break;
-                 }
-             }
+               }
+             else if (!vect_stmt_dominates_stmt_p (last_stmt, use_stmt))
+               can_insert = false;
+             if (!can_insert)
+               {
+                 if (dump_enabled_p ())
+                   dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                                    "Cannot determine insertion place for "
+                                    "lane extract of %T at node %p\n",
+                                    DEF_FROM_PTR (def_p), (void *)node);
+                 can_insert = false;
+                 break;
+               }
+           }
          if (live_p && can_insert)
            {
              /* Only record a live stmt when we can replace all uses.  We
-- 
2.51.0

Reply via email to