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 <rguent...@suse.de> Date: Fri, 23 Nov 2018 09:53:37 +0100 Subject: [PATCH] fix-pr88149 2018-11-23 Richard Biener <rguent...@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; }