[PATCH] Fix PR88149

Richard Biener rguenther@suse.de
Fri Nov 23 12:52:00 GMT 2018


The following fixes an old issue with BB vectorization demoting some
SLP nodes to external (built up from scalars).  If we have the
same operand in a stmt but with different such state we get
confused.

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

Richard.

>From b1b52fc997b8229fbdd12052c7cfe7ac7ff29fa1 Mon Sep 17 00:00:00 2001
From: Richard Guenther <rguenther@suse.de>
Date: Fri, 23 Nov 2018 09:53:37 +0100
Subject: [PATCH] fix-pr88149

2018-11-23  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/88149
	* tree-vect-slp.c (vect_slp_analyze_node_operations): Detect
	the case where there are two different def types for the
	same operand at different operand position in the same stmt.

	* g++.dg/torture/pr88149.C: New testcase.

diff --git a/gcc/testsuite/g++.dg/torture/pr88149.C b/gcc/testsuite/g++.dg/torture/pr88149.C
new file mode 100644
index 00000000000..2700a091740
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr88149.C
@@ -0,0 +1,63 @@
+// { dg-do compile }
+// { dg-additional-options "-ftree-vectorize" }
+
+template <typename> struct a;
+template <typename b> struct a<b *> {
+  typedef long c;
+  typedef b &d;
+};
+template <typename e> class f {
+  e ab;
+  typedef a<e> ac;
+
+public:
+  typename ac::d operator[](typename ac::c o) { return ab[o]; }
+};
+template <typename> struct au;
+template <typename b> au<b> operator+(au<b> o, au<b> p2) {
+  au<b> ax = o;
+  ax += p2;
+  return ax;
+}
+template <typename b> au<b> operator-(au<b> o, au<b> p2) {
+  au<b> ax = o;
+  ax -= p2;
+  return ax;
+}
+template <typename b> au<b> operator*(au<b>, au<b> &p2) {
+  au<b> ax;
+  ax *= p2;
+  return ax;
+}
+template <> struct au<double> {
+  double p() { return __real__ az; }
+  double q() { return __imag__ az; }
+  void operator+=(au o) {
+    az += o.p();
+    __imag__ az += o.q();
+  }
+  void operator-=(au o) {
+    az -= o.p();
+    __imag__ az -= o.q();
+  }
+  void operator*=(au &o) {
+    _Complex bd = o.p();
+    __imag__ bd = o.q();
+    az *= bd;
+  }
+  _Complex az;
+};
+long bm, m;
+f<au<double> *> g;
+au<double> h, i, l;
+void bn() {
+  au<double> bq;
+  for (long k; m;) {
+    au<double> br;
+    for (long j = 0; j < bm; ++j) {
+      au<double> n = br * h;
+      i = l + n;
+      g[k] = l - bq;
+    }
+  }
+}
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index f2bb8da9de2..9e805d07726 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -2557,22 +2557,46 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
 					   visited, lvisited, cost_vec))
       return false;
 
+  /* ???  We have to catch the case late where two first scalar stmts appear
+     in multiple SLP children with different def type and fail.  Remember
+     original def types first since SLP_TREE_DEF_TYPE doesn't necessarily
+     match it when that is vect_internal_def.  */
+  auto_vec<vect_def_type, 4> dt;
+  dt.safe_grow (SLP_TREE_CHILDREN (node).length ());
+  FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
+    dt[j] = STMT_VINFO_DEF_TYPE (SLP_TREE_SCALAR_STMTS (child)[0]);
+
   /* Push SLP node def-type to stmt operands.  */
   FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
     if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
       STMT_VINFO_DEF_TYPE (SLP_TREE_SCALAR_STMTS (child)[0])
 	= SLP_TREE_DEF_TYPE (child);
-  bool res = vect_slp_analyze_node_operations_1 (vinfo, node, node_instance,
-						 cost_vec);
-  /* Restore def-types.  */
+
+  /* Check everything worked out.  */
+  bool res = true;
   FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
     if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
-      STMT_VINFO_DEF_TYPE (SLP_TREE_SCALAR_STMTS (child)[0])
-	= vect_internal_def;
-  if (! res)
-    return false;
+      {
+	if (STMT_VINFO_DEF_TYPE (SLP_TREE_SCALAR_STMTS (child)[0])
+	    != SLP_TREE_DEF_TYPE (child))
+	  res = false;
+      }
+    else if (STMT_VINFO_DEF_TYPE (SLP_TREE_SCALAR_STMTS (child)[0]) != dt[j])
+      res = false;
+  if (!res && dump_enabled_p ())
+    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+		     "not vectorized: same operand with different "
+		     "def type in stmt.\n");
 
-  return true;
+  if (res)
+    res = vect_slp_analyze_node_operations_1 (vinfo, node, node_instance,
+					      cost_vec);
+
+  /* Restore def-types.  */
+  FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
+    STMT_VINFO_DEF_TYPE (SLP_TREE_SCALAR_STMTS (child)[0]) = dt[j];
+
+  return res;
 }
 
 



More information about the Gcc-patches mailing list