Richard Biener <rguent...@suse.de> writes: > So I came up with this, yet another overload of vect_is_simple_use (ick). > But at least for the two functions I tackled it seems to be straight-forward. > > I'll see to enforce a type on all invariants in vect_get_constant_vectors > and thus try to adjust all other vectorizable_* (but I'm sure I'll miss > some...). > > Comments still welcome. The patch below passes vect.exp testing on > x86_64-linux.
LGTM FWIW. Just wondering... > @@ -11710,6 +11735,58 @@ vect_is_simple_use (tree operand, vec_info *vinfo, > enum vect_def_type *dt, > return true; > } > > +/* Function vect_is_simple_use. > + > + Same as vect_is_simple_use but determines the operand by operand > + position OPERAND from either STMT or SLP_NODE, filling in *OP > + and *SLP_DEF (when SLP_NODE is not NULL). */ > + > +bool > +vect_is_simple_use (vec_info *vinfo, stmt_vec_info stmt, slp_tree slp_node, > + unsigned operand, tree *op, slp_tree *slp_def, > + enum vect_def_type *dt, > + tree *vectype, stmt_vec_info *def_stmt_info_out) > +{ > + if (slp_node) > + { > + if (operand >= SLP_TREE_CHILDREN (slp_node).length ()) > + return false; ...which case needs the return false? Asserting for out-of-range indices (like for !slp_node) feels like it would hide fewer bugs. Thanks, Richard > + slp_tree child = SLP_TREE_CHILDREN (slp_node)[operand]; > + *slp_def = child; > + if (SLP_TREE_DEF_TYPE (child) == vect_internal_def) > + *op = gimple_get_lhs (SLP_TREE_SCALAR_STMTS (child)[0]->stmt); > + else > + *op = SLP_TREE_SCALAR_OPS (child)[0]; > + } > + else > + { > + if (gassign *ass = dyn_cast <gassign *> (stmt->stmt)) > + *op = gimple_op (ass, operand + 1); > + else if (gcall *call = dyn_cast <gcall *> (stmt->stmt)) > + *op = gimple_call_arg (call, operand); > + else > + gcc_unreachable (); > + } > + > + /* ??? We might want to update *vectype from *slp_def here though > + when sharing nodes this would prevent unsharing in the caller. */ > + return vect_is_simple_use (*op, vinfo, dt, vectype, def_stmt_info_out); > +} > + > +/* If OP is not NULL and is external or constant update its vector > + type with VECTYPE. Returns true if successful or false if not, > + for example when conflicting vector types are present. */ > + > +bool > +vect_maybe_update_slp_op_vectype (slp_tree op, tree vectype) > +{ > + if (!op || SLP_TREE_DEF_TYPE (op) == vect_internal_def) > + return true; > + if (SLP_TREE_VECTYPE (op)) > + return types_compatible_p (SLP_TREE_VECTYPE (op), vectype); > + SLP_TREE_VECTYPE (op) = vectype; > + return true; > +} > > /* Function supportable_widening_operation > > diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h > index 38a0a1d278b..5b4188d08a3 100644 > --- a/gcc/tree-vectorizer.h > +++ b/gcc/tree-vectorizer.h > @@ -1695,6 +1695,11 @@ extern bool vect_is_simple_use (tree, vec_info *, enum > vect_def_type *, > extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *, > tree *, stmt_vec_info * = NULL, > gimple ** = NULL); > +extern bool vect_is_simple_use (vec_info *, stmt_vec_info, slp_tree, > + unsigned, tree *, slp_tree *, > + enum vect_def_type *, > + tree *, stmt_vec_info * = NULL); > +extern bool vect_maybe_update_slp_op_vectype (slp_tree, tree); > extern bool supportable_widening_operation (vec_info *, > enum tree_code, stmt_vec_info, > tree, tree, enum tree_code *,