return true;
}
-static hash_set <vec <gimple *>, bst_traits> *bst_fail;
+typedef hash_set <vec <gimple *>, bst_traits> scalar_stmts_set_t;
+static scalar_stmts_set_t *bst_fail;
static slp_tree
vect_build_slp_tree_2 (vec_info *vinfo,
vect_analyze_slp_cost_1 (slp_instance instance, slp_tree node,
stmt_vector_for_cost *prologue_cost_vec,
stmt_vector_for_cost *body_cost_vec,
- unsigned ncopies_for_cost)
+ unsigned ncopies_for_cost,
+ scalar_stmts_set_t* visited)
{
unsigned i, j;
slp_tree child;
stmt_vec_info stmt_info;
tree lhs;
+ /* If we already costed the exact same set of scalar stmts we're done.
+ We share the generated vector stmts for those. */
+ if (visited->contains (SLP_TREE_SCALAR_STMTS (node)))
+ return;
+
+ visited->add (SLP_TREE_SCALAR_STMTS (node).copy ());
+
/* Recurse down the SLP tree. */
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
vect_analyze_slp_cost_1 (instance, child, prologue_cost_vec,
- body_cost_vec, ncopies_for_cost);
+ body_cost_vec, ncopies_for_cost, visited);
/* Look at the first scalar stmt to determine the cost. */
stmt = SLP_TREE_SCALAR_STMTS (node)[0];
prologue_cost_vec.create (10);
body_cost_vec.create (10);
+ scalar_stmts_set_t *visited = new scalar_stmts_set_t ();
vect_analyze_slp_cost_1 (instance, SLP_INSTANCE_TREE (instance),
&prologue_cost_vec, &body_cost_vec,
- ncopies_for_cost);
+ ncopies_for_cost, visited);
+ delete visited;
/* Record the prologue costs, which were delayed until we were
sure that SLP was successful. */
/* Build the tree for the SLP instance. */
bool *matches = XALLOCAVEC (bool, group_size);
unsigned npermutes = 0;
- bst_fail = new hash_set <vec <gimple *>, bst_traits> ();
+ bst_fail = new scalar_stmts_set_t ();
node = vect_build_slp_tree (vinfo, scalar_stmts, group_size,
&max_nunits, &loads, matches, &npermutes,
NULL, max_tree_size);
return true;
}
-
+typedef hash_map <vec <gimple *>, slp_tree,
+ simple_hashmap_traits <bst_traits, slp_tree> >
+ scalar_stmts_to_slp_tree_map_t;
/* Vectorize SLP instance tree in postorder. */
static bool
-vect_schedule_slp_instance (slp_tree node, slp_instance instance)
+vect_schedule_slp_instance (slp_tree node, slp_instance instance,
+ scalar_stmts_to_slp_tree_map_t *bst_map)
{
gimple *stmt;
bool grouped_store, is_store;
if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
return false;
+ /* See if we have already vectorized the same set of stmts and reuse their
+ vectorized stmts. */
+ slp_tree &leader
+ = bst_map->get_or_insert (SLP_TREE_SCALAR_STMTS (node).copy ());
+ if (leader)
+ {
+ SLP_TREE_VEC_STMTS (node).safe_splice (SLP_TREE_VEC_STMTS (leader));
+ return false;
+ }
+
+ leader = node;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- vect_schedule_slp_instance (child, instance);
+ vect_schedule_slp_instance (child, instance, bst_map);
/* Push SLP node def-type to stmts. */
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
FOR_EACH_VEC_ELT (slp_instances, i, instance)
{
/* Schedule the tree of INSTANCE. */
+ scalar_stmts_to_slp_tree_map_t *bst_map
+ = new scalar_stmts_to_slp_tree_map_t ();
is_store = vect_schedule_slp_instance (SLP_INSTANCE_TREE (instance),
- instance);
+ instance, bst_map);
+ delete bst_map;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"vectorizing stmts using SLP.\n");