Hi! Even if vect_build_slp_tree on child fails, it might have pushed some nodes to SLP_TREE_CHILDREN (child) vector before returning false. If we retry, we need to start with no grandchildren of course.
Bootstrapped/regtested on x86_64-linux and i686-linux, acked by Richard in the PR, committed to trunk so far. 2015-03-24 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/65533 * tree-vect-slp.c (vect_build_slp_tree): Before re-trying with swapped operands, call vect_free_slp_tree on SLP_TREE_CHILDREN of child and truncate the SLP_TREE_CHILDREN vector. * gcc.dg/pr65533.c: New test. --- gcc/tree-vect-slp.c.jj 2015-03-23 16:15:30.000000000 +0100 +++ gcc/tree-vect-slp.c 2015-03-24 08:54:51.524143880 +0100 @@ -1035,13 +1035,20 @@ vect_build_slp_tree (loop_vec_info loop_ behavior. */ && *npermutes < 4) { + unsigned int j; + slp_tree grandchild; + /* Roll back. */ *max_nunits = old_max_nunits; loads->truncate (old_nloads); + FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild) + vect_free_slp_tree (grandchild); + SLP_TREE_CHILDREN (child).truncate (0); + /* Swap mismatched definition stmts. */ dump_printf_loc (MSG_NOTE, vect_location, "Re-trying with swapped operands of stmts "); - for (unsigned j = 0; j < group_size; ++j) + for (j = 0; j < group_size; ++j) if (!matches[j]) { gimple tem = oprnds_info[0]->def_stmts[j]; --- gcc/testsuite/gcc.dg/pr65533.c.jj 2015-03-24 08:52:24.437577841 +0100 +++ gcc/testsuite/gcc.dg/pr65533.c 2015-03-24 08:51:55.000000000 +0100 @@ -0,0 +1,25 @@ +/* PR tree-optimization/65533 */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -w" } */ + +struct A { int a[2]; }; +struct B { double b[2]; }; +struct C { double c[4][1]; }; + +static inline void +bar (struct B *x, double y, double z) +{ + x->b[0] = y; + x->b[1] = z; +} + +void baz (struct B *); + +void +foo (struct C *x, struct A *y) +{ + struct B d; + bar (&d, x->c[1][0] * y->a[0] + x->c[0][1] * y->a[1] + x->c[0][0] * x->c[0][1], + x->c[0][0] * y->a[0] + x->c[0][1] * y->a[1] + x->c[0][1] * y->a[0] + x->c[0][0]); + baz (&d); +} Jakub