From: Richard Biener Date: Mon, 13 Jul 2020 10:41:35 +0000 (+0200) Subject: tree-optimization/96163 - fix placement issue with SLP and vectors X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c4facd483de2d5b6b4d20e6ad74c85b9f1eba41a;p=gcc.git tree-optimization/96163 - fix placement issue with SLP and vectors This avoids placing stmts beyond the vectorizer region begin which confuses vect_stmt_dominates_stmt_p. 2020-07-13 Richard Biener PR tree-optimization/96163 * tree-vect-slp.c (vect_schedule_slp_instance): Put new stmts at least after region begin. * g++.dg/vect/pr96163.cc: New testcase. --- diff --git a/gcc/testsuite/g++.dg/vect/pr96163.cc b/gcc/testsuite/g++.dg/vect/pr96163.cc new file mode 100644 index 00000000000..3bd376f67f6 --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/pr96163.cc @@ -0,0 +1,146 @@ +// { dg-do compile } +// { dg-require-effective-target c++17 } + +typedef double b __attribute__((__vector_size__(16))); +b c; +enum { d }; +namespace e { +template struct g; +struct h { + enum { i, j }; +}; +template struct aa; +} // namespace e +template struct k; +template class l; +template class ab; +template class o; +template class ac; +class p; +namespace e { +template struct q { typedef ac> ae; }; +struct s { + template void af(double *ak, t) { *(b *)ak = c; } +}; +} // namespace e +template class ab : public k {}; +template class ab : public ab { +public: + typedef typename e::g::ag ag; + using ab::ah; + ag ai() { + long aj = 0; + return e::aa(ah()).ai(aj); + } + ag operator[](long) { return ai(); } +}; +template class ay : public ab { +public: + enum { a, al }; +}; +template class ac : public ay { +public: + p am(); +}; +template struct k { + o &ah() { return *static_cast *>(this); } +}; +namespace e { +template struct aa { aa(f); }; +template struct aa> { + typedef ad ao; + typedef typename ao::ag ag; + aa(ao &ak) : ap(ak.aq()) {} + ag &ai(long ak) { return ap[ak]; } + ag *ap; +}; +template +struct aa> : aa>> { + typedef o aw; + aa(aw &ak) : aa>(ak) {} +}; +template struct u { + enum { az, ba, bb }; + static void bc(ax ak) { ak.template be(az, ba); } +}; +template struct v { + static void bc(ax ak) { u::bc(ak); } +}; +template class w { + typedef bg bi; + +public: + typedef bg bj; + typedef bg bf; + w(bj ak, int, bh, bi x) : bk(ak), bl(x) {} + template void be(long, long) { + bn.template af(&bk.ai(0), 0); + } + bj bk; + bh bn; + bi bl; +}; +template void bp(bi &ak, bo, bh bq) { + typedef aa bj; + bo br; + bj bs(ak); + typedef w ax; + ax bd(bs, br, bq, ak); + v::bc(bd); +} +template struct bt; +template void bx(bu &ak, bv by, bw bq) { + bt::bc(ak, by, bq); +} +template struct bt { + static void bc(o &ak, int by, s bq) { bp(ak, by, bq); } +}; +} // namespace e +class bz { +public: + template void operator*(an); +}; +namespace e { +template struct cb { double am[ca]; }; +} // namespace e +template class cc { + e::cb ap; + +public: + double *aq() { return ap.am; } +}; +template class l : public e::q::ae { +public: + typedef typename e::q::ae cd; + typedef typename e::g::ag ag; + cc ce; + ag *aq() { return ce.aq(); } + l() {} + template l(an ak) { bx(this->ah(), ak, e::s()); } + template void ch(cf, cg by) { + ag *z, *y; + { z = aq(); } + y = z; + y[0] = aq()[1] = by; + } +}; +namespace e { +template +struct g> { + typedef ci ag; +}; +} // namespace e +template +class o : public l> { +public: + typedef l cd; + template o(cf ak, cg by) { cd::ch(ak, by); } + template o(an ak) : cd(ak) {} +}; +class p : public bz {}; +double cq; +void cm() { + o r = 0; + o cn = r; + cn.am() * o(0, r[0] / cq).am(); +} diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index b3645b0a820..72192b5a813 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -4404,18 +4404,26 @@ vect_schedule_slp_instance (vec_info *vinfo, else { /* For externals we have to look at all defs since their - insertion place is decided per vector. */ - unsigned j; - tree vdef; - FOR_EACH_VEC_ELT (SLP_TREE_VEC_DEFS (child), j, vdef) - if (TREE_CODE (vdef) == SSA_NAME - && !SSA_NAME_IS_DEFAULT_DEF (vdef)) - { - gimple *vstmt = SSA_NAME_DEF_STMT (vdef); - if (!last_stmt - || vect_stmt_dominates_stmt_p (last_stmt, vstmt)) - last_stmt = vstmt; - } + insertion place is decided per vector. But beware + of pre-existing vectors where we need to make sure + we do not insert before the region boundary. */ + if (SLP_TREE_SCALAR_OPS (child).is_empty () + && !vinfo->lookup_def (SLP_TREE_VEC_DEFS (child)[0])) + last_stmt = gsi_stmt (as_a (vinfo)->region_begin); + else + { + unsigned j; + tree vdef; + FOR_EACH_VEC_ELT (SLP_TREE_VEC_DEFS (child), j, vdef) + if (TREE_CODE (vdef) == SSA_NAME + && !SSA_NAME_IS_DEFAULT_DEF (vdef)) + { + gimple *vstmt = SSA_NAME_DEF_STMT (vdef); + if (!last_stmt + || vect_stmt_dominates_stmt_p (last_stmt, vstmt)) + last_stmt = vstmt; + } + } } /* This can happen when all children are pre-existing vectors or constants. */