The following moves dealing with extern vector defs in internal
permute nodes to where it is more appropriate and also catches
the failing stmt-based dominance check from the testcase in PR128347.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.  Will
push when that succeeds.

Richard.

        PR tree-optimization/128347
        * tree-vect-slp.cc (vect_schedule_slp_node): Move extern
        vector def fixup.

        * g++.dg/vect/pr128347.cc: New testcase.
---
 gcc/testsuite/g++.dg/vect/pr128347.cc | 38 +++++++++++++++++++++++++++
 gcc/tree-vect-slp.cc                  | 19 +++++++-------
 2 files changed, 47 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/vect/pr128347.cc

diff --git a/gcc/testsuite/g++.dg/vect/pr128347.cc 
b/gcc/testsuite/g++.dg/vect/pr128347.cc
new file mode 100644
index 00000000000..80f876f4ffa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr128347.cc
@@ -0,0 +1,38 @@
+// { dg-do compile }
+
+struct vector {
+  ~vector();
+};
+int expand_dx;
+template <int SIZE> struct Tuple {
+  template <typename IdxT> int &operator[](IdxT i) { return mm[i]; }
+  int mm[SIZE];
+};
+struct Vec3 : Tuple<3> {
+  void x();
+  void operator-=(Vec3 v1) {
+    mm[0] -= v1[0];
+    mm[1] -= v1[1];
+  }
+};
+struct BBox {
+  Vec3 extents() {
+    Vec3 __trans_tmp_2, result(mMax);
+    result -= mMin;
+    __trans_tmp_2 = result;
+    return __trans_tmp_2;
+  }
+  void expand() {
+    for (int i = 0; i < 3; ++i)
+      mMin[i] -= mMax[i] += expand_dx;
+  }
+  Vec3 mMin, mMax;
+};
+int size();
+void TestBody() {
+  vector points;
+  BBox region;
+  region.expand();
+  if (size())
+    region.extents().x();
+}
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index ae73837a76d..87a235f28b1 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -12335,7 +12335,15 @@ vect_schedule_slp_node (vec_info *vinfo,
                  && !SSA_NAME_IS_DEFAULT_DEF (vdef))
                {
                  gimple *vstmt = SSA_NAME_DEF_STMT (vdef);
-                 if (!last_stmt)
+                 /* Ignore existing external vector defs so we insert
+                    at region boundary.  Those can leak to an
+                    internal identity permute node.  */
+                 if (is_a <bb_vec_info> (vinfo)
+                     && vinfo->bbs[0] != gimple_bb (vstmt)
+                     && dominated_by_p (CDI_DOMINATORS, vinfo->bbs[0],
+                                        gimple_bb (vstmt)))
+                   ;
+                 else if (!last_stmt)
                    last_stmt = vstmt;
                  else if (vect_stmt_dominates_stmt_p (last_stmt, vstmt))
                    last_stmt = vstmt;
@@ -12396,15 +12404,6 @@ vect_schedule_slp_node (vec_info *vinfo,
              }
          }
 
-      /* When we face existing vector defs that are external, make sure
-        to insert at region boundary.  */
-      if (last_stmt
-         && is_a <bb_vec_info> (vinfo)
-         && vinfo->bbs[0] != gimple_bb (last_stmt)
-         && dominated_by_p (CDI_DOMINATORS, vinfo->bbs[0],
-                            gimple_bb (last_stmt)))
-       last_stmt = NULL;
-
       /* We split regions to vectorize at control altering stmts
         with a definition so this can only be an external.  */
       gcc_checking_assert (!last_stmt
-- 
2.51.0

Reply via email to