+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.
+
2018-23-11 Mihail Ionescu <mihail.ionescu@arm.com>
* config/arm/arm.c (arm_expand_compare_and_swap): Simplify and call
--- /dev/null
+// { 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;
+ }
+ }
+}
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;
}