diff mbox series

tree-optimization/116674 - vectorizable_simd_clone_call and re-analysis

Message ID 20240911125620.76B003858406@sourceware.org
State New
Headers show
Series tree-optimization/116674 - vectorizable_simd_clone_call and re-analysis | expand

Commit Message

Richard Biener Sept. 11, 2024, 12:55 p.m. UTC
When SLP analysis scraps an instance because it fails to analyze we
can end up calling vectorizable_* in analysis mode on a node that
was analyzed during the analysis of that instance again.
vectorizable_simd_clone_call wasn't expecting that and instead
guarded analysis/transform code on populated data structures.
The following changes it so it survives re-analysis.

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

	PR tree-optimization/116674
	* tree-vect-stmts.cc (vectorizable_simd_clone_call): Support
	re-analysis.

	* g++.dg/vect/pr116674.cc: New testcase.
---
 gcc/testsuite/g++.dg/vect/pr116674.cc | 85 +++++++++++++++++++++++++++
 gcc/tree-vect-stmts.cc                |  8 ++-
 2 files changed, 90 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/vect/pr116674.cc
diff mbox series

Patch

diff --git a/gcc/testsuite/g++.dg/vect/pr116674.cc b/gcc/testsuite/g++.dg/vect/pr116674.cc
new file mode 100644
index 00000000000..1c13f12290b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr116674.cc
@@ -0,0 +1,85 @@ 
+// { dg-do compile }
+// { dg-require-effective-target c++11 }
+// { dg-additional-options "-Ofast" }
+// { dg-additional-options "-march=x86-64-v3" { target { x86_64-*-* i?86-*-* } } }
+
+namespace std {
+    typedef int a;
+    template <typename> struct b;
+    template <typename> class aa {};
+    template <typename c> c d(c e, c) { return e; }
+    template <typename c> struct b<aa<c>> {
+	using f = c;
+	using g = c *;
+	template <typename h> using j = aa<h>;
+    };
+} // namespace std
+namespace l {
+    template <typename ab> struct m : std::b<ab> {
+	typedef std::b<ab> n;
+	typedef typename n::f &q;
+	template <typename c> struct ac { typedef typename n::j<c> ad; };
+    };
+} // namespace l
+namespace std {
+    template <typename c, typename ab> struct o {
+	typedef typename l::m<ab>::ac<c>::ad ae;
+	typedef typename l::m<ae>::g g;
+	struct p {
+	    g af;
+	};
+	struct ag : p {
+	    ag(ae) {}
+	};
+	typedef ab u;
+	o(a, u e) : ah(e) {}
+	ag ah;
+    };
+    template <typename c, typename ab = aa<c>> class r : o<c, ab> {
+	typedef o<c, ab> s;
+	typedef typename s::ae ae;
+	typedef l::m<ae> w;
+
+    public:
+	c f;
+	typedef typename w::q q;
+	typedef a t;
+	typedef ab u;
+	r(t x, u e = u()) : s(ai(x, e), e) {}
+	q operator[](t x) { return *(this->ah.af + x); }
+	t ai(t x, u) { return x; }
+    };
+    extern "C" __attribute__((__simd__)) double exp(double);
+} // namespace std
+using namespace std;
+int ak;
+double v, y;
+void am(double, int an, double, double, double, double, double, double, double,
+	double, double, double, int, double, double, double, double,
+	r<double> ap, double, double, double, double, double, double, double,
+	double, r<double> ar, r<double> as, double, double, r<double> at,
+	r<double> au, r<double> av, double, double) {
+    double ba;
+    for (int k;;)
+      for (int i; i < an; ++i) {
+	  y = i;
+	  v = d(y, 25.0);
+	  ba = exp(v);
+	  ar[i * (ak + 1)] = ba;
+	  as[i * (ak + 1)] = ar[i * (ak + 1)];
+	  if (k && ap[k]) {
+	      at[i * (ak + 1)] = av[i * (ak + 1)] = as[i * (ak + 1)];
+	      au[i * (ak + 1)] = ar[i * (ak + 1)];
+	  } else {
+	      au[i * (ak + 1)] = ba;
+	      at[i * (ak + 1)] = av[i * (ak + 1)] = k;
+	  }
+      }
+}
+void b(int bc) {
+    double bd, be, bf, bg, bh, ao, ap, bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx,
+    by, aq, ar, as, bz, ca, at, au, av, cb, aw;
+    int bi;
+    am(bh, bc, bi, bi, bi, bi, bv, bw, bx, by, bu, bt, bi, ao, bn, bo, bp, ap, bq,
+       br, bs, bd, be, bf, bg, aq, ar, as, bz, ca, at, au, av, cb, aw);
+}
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 22d50263cdd..1d919ad2516 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -3987,6 +3987,8 @@  vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
 
   vec<tree>& simd_clone_info = (slp_node ? SLP_TREE_SIMD_CLONE_INFO (slp_node)
 				: STMT_VINFO_SIMD_CLONE_INFO (stmt_info));
+  if (!vec_stmt)
+    simd_clone_info.truncate (0);
   arginfo.reserve (nargs, true);
   auto_vec<slp_tree> slp_op;
   slp_op.safe_grow_cleared (nargs);
@@ -4035,10 +4037,10 @@  vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
 
       /* For linear arguments, the analyze phase should have saved
 	 the base and step in {STMT_VINFO,SLP_TREE}_SIMD_CLONE_INFO.  */
-      if (i * 3 + 4 <= simd_clone_info.length ()
+      if (vec_stmt
+	  && i * 3 + 4 <= simd_clone_info.length ()
 	  && simd_clone_info[i * 3 + 2])
 	{
-	  gcc_assert (vec_stmt);
 	  thisarginfo.linear_step = tree_to_shwi (simd_clone_info[i * 3 + 2]);
 	  thisarginfo.op = simd_clone_info[i * 3 + 1];
 	  thisarginfo.simd_lane_linear
@@ -4093,7 +4095,7 @@  vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
   unsigned group_size = slp_node ? SLP_TREE_LANES (slp_node) : 1;
   unsigned int badness = 0;
   struct cgraph_node *bestn = NULL;
-  if (simd_clone_info.exists ())
+  if (vec_stmt)
     bestn = cgraph_node::get (simd_clone_info[0]);
   else
     for (struct cgraph_node *n = node->simd_clones; n != NULL;