Commit 10a73df7 by Richard Biener Committed by Richard Biener

re PR tree-optimization/92516 (ICE in vect_schedule_slp_instance, at…

re PR tree-optimization/92516 (ICE in vect_schedule_slp_instance, at tree-vect-slp.c:4095 since r278246)

2019-11-18  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/92516
	* tree-vect-slp.c (vect_analyze_slp_instance): Add bst_map
	argument, hoist bst_map creation/destruction to ...
	(vect_analyze_slp): ... here, forming a true graph with
	SLP instances being the entries.
	(vect_detect_hybrid_slp_stmts): Remove wrapper.
	(vect_detect_hybrid_slp): Use one visited set for all
	graph entries.
	(vect_slp_analyze_node_operations): Simplify visited/lvisited
	to hash-sets of slp_tree.
	(vect_slp_analyze_operations): Likewise.
	(vect_bb_slp_scalar_cost): Remove wrapper.
	(vect_bb_vectorization_profitable_p): Use one visited set for
	all graph entries.
	(vect_schedule_slp_instance): Elide bst_map use.
	(vect_schedule_slp): Likewise.

	* g++.dg/vect/slp-pr92516.cc: New testcase.

2019-11-18  Richard Biener  <rguenther@suse.de>

	* tree-vect-slp.c (vect_analyze_slp_instance): When a CTOR
	was vectorized with just external refs fail.

	* gcc.dg/vect/vect-ctor-1.c: New testcase.

From-SVN: r278406
parent 33b3af3f
2019-11-18 Richard Biener <rguenther@suse.de>
PR tree-optimization/92516
* tree-vect-slp.c (vect_analyze_slp_instance): Add bst_map
argument, hoist bst_map creation/destruction to ...
(vect_analyze_slp): ... here, forming a true graph with
SLP instances being the entries.
(vect_detect_hybrid_slp_stmts): Remove wrapper.
(vect_detect_hybrid_slp): Use one visited set for all
graph entries.
(vect_slp_analyze_node_operations): Simplify visited/lvisited
to hash-sets of slp_tree.
(vect_slp_analyze_operations): Likewise.
(vect_bb_slp_scalar_cost): Remove wrapper.
(vect_bb_vectorization_profitable_p): Use one visited set for
all graph entries.
(vect_schedule_slp_instance): Elide bst_map use.
(vect_schedule_slp): Likewise.
2019-11-18 Richard Biener <rguenther@suse.de>
* tree-vect-slp.c (vect_analyze_slp_instance): When a CTOR
was vectorized with just external refs fail.
2019-11-18 Martin Liska <mliska@suse.cz> 2019-11-18 Martin Liska <mliska@suse.cz>
PR ipa/92525 PR ipa/92525
2019-11-18 Richard Biener <rguenther@suse.de>
PR tree-optimization/92516
* g++.dg/vect/slp-pr92516.cc: New testcase.
2019-11-18 Richard Biener <rguenther@suse.de>
* gcc.dg/vect/vect-ctor-1.c: New testcase.
2019-11-18 Martin Liska <mliska@suse.cz> 2019-11-18 Martin Liska <mliska@suse.cz>
* gcc.dg/ipa/ipa-icf-36.c: Remove 'all-all-all'. * gcc.dg/ipa/ipa-icf-36.c: Remove 'all-all-all'.
......
// { dg-do compile }
// { dg-require-effective-target c++14 }
class a {
public:
typedef int b;
operator b();
};
class c {
public:
constexpr int m_fn1() const;
constexpr int d() const;
int e;
int f;
};
constexpr int c::m_fn1() const { return e; }
constexpr int c::d() const { return f; }
class g {
public:
g();
constexpr void i(const c &) noexcept;
int j;
int k;
int l;
int m;
};
constexpr void g::i(const c &n) noexcept {
int v = l - j, h = m - k;
j = n.m_fn1() - v / 2;
k = n.d() - h / 2;
l = j + v;
m = k + h;
}
class o {
void m_fn4() const;
a p;
} r;
void o::m_fn4() const {
g q;
c t;
q.i(t);
r.p || 0;
}
/* { dg-do compile } */
/* { dg-additional-options "-O3" } */
/* { dg-additional-options "-mavx2" { target { i?86-*-* x86_64-*-* } } } */
typedef struct {
unsigned short mprr_2[5][16][16];
} ImageParameters;
int s[16][2];
void intrapred_luma_16x16(ImageParameters *img, int s0)
{
for (int j=0; j < 16; j++)
for (int i=0; i < 16; i++)
{
img->mprr_2[1 ][j][i]=s[j][1];
img->mprr_2[2 ][j][i]=s0;
}
}
...@@ -2087,6 +2087,7 @@ calculate_unrolling_factor (poly_uint64 nunits, unsigned int group_size) ...@@ -2087,6 +2087,7 @@ calculate_unrolling_factor (poly_uint64 nunits, unsigned int group_size)
static bool static bool
vect_analyze_slp_instance (vec_info *vinfo, vect_analyze_slp_instance (vec_info *vinfo,
scalar_stmts_to_slp_tree_map_t *bst_map,
stmt_vec_info stmt_info, unsigned max_tree_size) stmt_vec_info stmt_info, unsigned max_tree_size)
{ {
slp_instance new_instance; slp_instance new_instance;
...@@ -2194,19 +2195,11 @@ vect_analyze_slp_instance (vec_info *vinfo, ...@@ -2194,19 +2195,11 @@ vect_analyze_slp_instance (vec_info *vinfo,
/* Build the tree for the SLP instance. */ /* Build the tree for the SLP instance. */
bool *matches = XALLOCAVEC (bool, group_size); bool *matches = XALLOCAVEC (bool, group_size);
unsigned npermutes = 0; unsigned npermutes = 0;
scalar_stmts_to_slp_tree_map_t *bst_map
= new scalar_stmts_to_slp_tree_map_t ();
poly_uint64 max_nunits = nunits; poly_uint64 max_nunits = nunits;
unsigned tree_size = 0; unsigned tree_size = 0;
node = vect_build_slp_tree (vinfo, scalar_stmts, group_size, node = vect_build_slp_tree (vinfo, scalar_stmts, group_size,
&max_nunits, matches, &npermutes, &max_nunits, matches, &npermutes,
&tree_size, bst_map); &tree_size, bst_map);
/* The map keeps a reference on SLP nodes built, release that. */
for (scalar_stmts_to_slp_tree_map_t::iterator it = bst_map->begin ();
it != bst_map->end (); ++it)
if ((*it).second)
vect_free_slp_tree ((*it).second, false);
delete bst_map;
if (node != NULL) if (node != NULL)
{ {
/* If this is a reduction chain with a conversion in front /* If this is a reduction chain with a conversion in front
...@@ -2260,6 +2253,18 @@ vect_analyze_slp_instance (vec_info *vinfo, ...@@ -2260,6 +2253,18 @@ vect_analyze_slp_instance (vec_info *vinfo,
matches[group_size / const_max_nunits * const_max_nunits] = false; matches[group_size / const_max_nunits * const_max_nunits] = false;
vect_free_slp_tree (node, false); vect_free_slp_tree (node, false);
} }
else if (constructor
&& SLP_TREE_DEF_TYPE (node) != vect_internal_def)
{
/* CONSTRUCTOR vectorization relies on a vector stmt being
generated, that doesn't work for fully external ones. */
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Build SLP failed: CONSTRUCTOR of external "
"or constant elements\n");
vect_free_slp_tree (node, false);
return false;
}
else else
{ {
/* Create a new SLP instance. */ /* Create a new SLP instance. */
...@@ -2394,7 +2399,7 @@ vect_analyze_slp_instance (vec_info *vinfo, ...@@ -2394,7 +2399,7 @@ vect_analyze_slp_instance (vec_info *vinfo,
stmt_vec_info rest = vect_split_slp_store_group (stmt_info, stmt_vec_info rest = vect_split_slp_store_group (stmt_info,
group1_size); group1_size);
bool res = vect_analyze_slp_instance (vinfo, stmt_info, bool res = vect_analyze_slp_instance (vinfo, bst_map, stmt_info,
max_tree_size); max_tree_size);
/* If the first non-match was in the middle of a vector, /* If the first non-match was in the middle of a vector,
skip the rest of that vector. */ skip the rest of that vector. */
...@@ -2405,7 +2410,8 @@ vect_analyze_slp_instance (vec_info *vinfo, ...@@ -2405,7 +2410,8 @@ vect_analyze_slp_instance (vec_info *vinfo,
rest = vect_split_slp_store_group (rest, const_nunits); rest = vect_split_slp_store_group (rest, const_nunits);
} }
if (i < group_size) if (i < group_size)
res |= vect_analyze_slp_instance (vinfo, rest, max_tree_size); res |= vect_analyze_slp_instance (vinfo, bst_map,
rest, max_tree_size);
return res; return res;
} }
/* Even though the first vector did not all match, we might be able to SLP /* Even though the first vector did not all match, we might be able to SLP
...@@ -2427,9 +2433,12 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) ...@@ -2427,9 +2433,12 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
DUMP_VECT_SCOPE ("vect_analyze_slp"); DUMP_VECT_SCOPE ("vect_analyze_slp");
scalar_stmts_to_slp_tree_map_t *bst_map
= new scalar_stmts_to_slp_tree_map_t ();
/* Find SLP sequences starting from groups of grouped stores. */ /* Find SLP sequences starting from groups of grouped stores. */
FOR_EACH_VEC_ELT (vinfo->grouped_stores, i, first_element) FOR_EACH_VEC_ELT (vinfo->grouped_stores, i, first_element)
vect_analyze_slp_instance (vinfo, first_element, max_tree_size); vect_analyze_slp_instance (vinfo, bst_map, first_element, max_tree_size);
if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo)) if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
{ {
...@@ -2437,7 +2446,7 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) ...@@ -2437,7 +2446,7 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
{ {
/* Find SLP sequences starting from reduction chains. */ /* Find SLP sequences starting from reduction chains. */
FOR_EACH_VEC_ELT (loop_vinfo->reduction_chains, i, first_element) FOR_EACH_VEC_ELT (loop_vinfo->reduction_chains, i, first_element)
if (! vect_analyze_slp_instance (vinfo, first_element, if (! vect_analyze_slp_instance (vinfo, bst_map, first_element,
max_tree_size)) max_tree_size))
{ {
/* Dissolve reduction chain group. */ /* Dissolve reduction chain group. */
...@@ -2459,10 +2468,17 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) ...@@ -2459,10 +2468,17 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
/* Find SLP sequences starting from groups of reductions. */ /* Find SLP sequences starting from groups of reductions. */
if (loop_vinfo->reductions.length () > 1) if (loop_vinfo->reductions.length () > 1)
vect_analyze_slp_instance (vinfo, loop_vinfo->reductions[0], vect_analyze_slp_instance (vinfo, bst_map, loop_vinfo->reductions[0],
max_tree_size); max_tree_size);
} }
/* The map keeps a reference on SLP nodes built, release that. */
for (scalar_stmts_to_slp_tree_map_t::iterator it = bst_map->begin ();
it != bst_map->end (); ++it)
if ((*it).second)
vect_free_slp_tree ((*it).second, false);
delete bst_map;
return opt_result::success (); return opt_result::success ();
} }
...@@ -2589,13 +2605,6 @@ vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype, ...@@ -2589,13 +2605,6 @@ vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype,
vect_detect_hybrid_slp_stmts (child, i, stype, visited); vect_detect_hybrid_slp_stmts (child, i, stype, visited);
} }
static void
vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype)
{
hash_map<slp_tree, unsigned> visited;
vect_detect_hybrid_slp_stmts (node, i, stype, visited);
}
/* Helpers for vect_detect_hybrid_slp walking pattern stmt uses. */ /* Helpers for vect_detect_hybrid_slp walking pattern stmt uses. */
static tree static tree
...@@ -2678,11 +2687,12 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo) ...@@ -2678,11 +2687,12 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
/* Then walk the SLP instance trees marking stmts with uses in /* Then walk the SLP instance trees marking stmts with uses in
non-SLP stmts as hybrid, also propagating hybrid down the non-SLP stmts as hybrid, also propagating hybrid down the
SLP tree, collecting the above info on-the-fly. */ SLP tree, collecting the above info on-the-fly. */
hash_map<slp_tree, unsigned> visited;
FOR_EACH_VEC_ELT (slp_instances, i, instance) FOR_EACH_VEC_ELT (slp_instances, i, instance)
{ {
for (unsigned i = 0; i < SLP_INSTANCE_GROUP_SIZE (instance); ++i) for (unsigned i = 0; i < SLP_INSTANCE_GROUP_SIZE (instance); ++i)
vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance), vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance),
i, pure_slp); i, pure_slp, visited);
} }
} }
...@@ -2830,8 +2840,8 @@ vect_slp_convert_to_external (vec_info *vinfo, slp_tree node, ...@@ -2830,8 +2840,8 @@ vect_slp_convert_to_external (vec_info *vinfo, slp_tree node,
static bool static bool
vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node, vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
slp_instance node_instance, slp_instance node_instance,
scalar_stmts_to_slp_tree_map_t *visited, hash_set<slp_tree> &visited,
scalar_stmts_to_slp_tree_map_t *lvisited, hash_set<slp_tree> &lvisited,
stmt_vector_for_cost *cost_vec) stmt_vector_for_cost *cost_vec)
{ {
int i, j; int i, j;
...@@ -2841,27 +2851,13 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node, ...@@ -2841,27 +2851,13 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
return true; return true;
/* If we already analyzed the exact same set of scalar stmts we're done. /* If we already analyzed the exact same set of scalar stmts we're done.
We share the generated vector stmts for those. */ We share the generated vector stmts for those.
slp_tree *leader; The SLP graph is acyclic so not caching whether we failed or succeeded
if ((leader = visited->get (SLP_TREE_SCALAR_STMTS (node)))
|| (leader = lvisited->get (SLP_TREE_SCALAR_STMTS (node))))
{
SLP_TREE_NUMBER_OF_VEC_STMTS (node)
= SLP_TREE_NUMBER_OF_VEC_STMTS (*leader);
/* Cope with cases in which we made a late decision to build the
node from scalars. */
if (SLP_TREE_DEF_TYPE (*leader) == vect_external_def
&& vect_slp_convert_to_external (vinfo, node, node_instance))
;
else
gcc_assert (SLP_TREE_DEF_TYPE (node) == SLP_TREE_DEF_TYPE (*leader));
return true;
}
/* The SLP graph is acyclic so not caching whether we failed or succeeded
doesn't result in any issue since we throw away the lvisited set doesn't result in any issue since we throw away the lvisited set
when we fail. */ when we fail. */
lvisited->put (SLP_TREE_SCALAR_STMTS (node).copy (), node); if (visited.contains (node)
|| lvisited.add (node))
return true;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child) FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
if (!vect_slp_analyze_node_operations (vinfo, child, node_instance, if (!vect_slp_analyze_node_operations (vinfo, child, node_instance,
...@@ -2934,16 +2930,15 @@ vect_slp_analyze_operations (vec_info *vinfo) ...@@ -2934,16 +2930,15 @@ vect_slp_analyze_operations (vec_info *vinfo)
DUMP_VECT_SCOPE ("vect_slp_analyze_operations"); DUMP_VECT_SCOPE ("vect_slp_analyze_operations");
scalar_stmts_to_slp_tree_map_t *visited hash_set<slp_tree> visited;
= new scalar_stmts_to_slp_tree_map_t ();
for (i = 0; vinfo->slp_instances.iterate (i, &instance); ) for (i = 0; vinfo->slp_instances.iterate (i, &instance); )
{ {
scalar_stmts_to_slp_tree_map_t lvisited; hash_set<slp_tree> lvisited;
stmt_vector_for_cost cost_vec; stmt_vector_for_cost cost_vec;
cost_vec.create (2); cost_vec.create (2);
if (!vect_slp_analyze_node_operations (vinfo, if (!vect_slp_analyze_node_operations (vinfo,
SLP_INSTANCE_TREE (instance), SLP_INSTANCE_TREE (instance),
instance, visited, &lvisited, instance, visited, lvisited,
&cost_vec)) &cost_vec))
{ {
slp_tree node = SLP_INSTANCE_TREE (instance); slp_tree node = SLP_INSTANCE_TREE (instance);
...@@ -2958,16 +2953,15 @@ vect_slp_analyze_operations (vec_info *vinfo) ...@@ -2958,16 +2953,15 @@ vect_slp_analyze_operations (vec_info *vinfo)
} }
else else
{ {
for (scalar_stmts_to_slp_tree_map_t::iterator x = lvisited.begin(); for (hash_set<slp_tree>::iterator x = lvisited.begin();
x != lvisited.end(); ++x) x != lvisited.end(); ++x)
visited->put ((*x).first.copy (), (*x).second); visited.add (*x);
i++; i++;
add_stmt_costs (vinfo->target_cost_data, &cost_vec); add_stmt_costs (vinfo->target_cost_data, &cost_vec);
cost_vec.release (); cost_vec.release ();
} }
} }
delete visited;
return !vinfo->slp_instances.is_empty (); return !vinfo->slp_instances.is_empty ();
} }
...@@ -3058,15 +3052,6 @@ vect_bb_slp_scalar_cost (basic_block bb, ...@@ -3058,15 +3052,6 @@ vect_bb_slp_scalar_cost (basic_block bb,
} }
} }
static void
vect_bb_slp_scalar_cost (basic_block bb,
slp_tree node, vec<bool, va_heap> *life,
stmt_vector_for_cost *cost_vec)
{
hash_set<slp_tree> visited;
vect_bb_slp_scalar_cost (bb, node, life, cost_vec, visited);
}
/* Check if vectorization of the basic block is profitable. */ /* Check if vectorization of the basic block is profitable. */
static bool static bool
...@@ -3081,13 +3066,14 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo) ...@@ -3081,13 +3066,14 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo)
/* Calculate scalar cost. */ /* Calculate scalar cost. */
stmt_vector_for_cost scalar_costs; stmt_vector_for_cost scalar_costs;
scalar_costs.create (0); scalar_costs.create (0);
hash_set<slp_tree> visited;
FOR_EACH_VEC_ELT (slp_instances, i, instance) FOR_EACH_VEC_ELT (slp_instances, i, instance)
{ {
auto_vec<bool, 20> life; auto_vec<bool, 20> life;
life.safe_grow_cleared (SLP_INSTANCE_GROUP_SIZE (instance)); life.safe_grow_cleared (SLP_INSTANCE_GROUP_SIZE (instance));
vect_bb_slp_scalar_cost (BB_VINFO_BB (bb_vinfo), vect_bb_slp_scalar_cost (BB_VINFO_BB (bb_vinfo),
SLP_INSTANCE_TREE (instance), SLP_INSTANCE_TREE (instance),
&life, &scalar_costs); &life, &scalar_costs, visited);
} }
void *target_cost_data = init_cost (NULL); void *target_cost_data = init_cost (NULL);
add_stmt_costs (target_cost_data, &scalar_costs); add_stmt_costs (target_cost_data, &scalar_costs);
...@@ -4128,8 +4114,7 @@ vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain, ...@@ -4128,8 +4114,7 @@ vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
/* Vectorize SLP instance tree in postorder. */ /* Vectorize SLP instance tree in postorder. */
static void static void
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_iterator si; gimple_stmt_iterator si;
stmt_vec_info stmt_info; stmt_vec_info stmt_info;
...@@ -4146,17 +4131,8 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance, ...@@ -4146,17 +4131,8 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
if (SLP_TREE_VEC_STMTS (node).exists ()) if (SLP_TREE_VEC_STMTS (node).exists ())
return; return;
/* See if we have already vectorized the same set of stmts and reuse their
vectorized stmts across instances. */
if (slp_tree *leader = bst_map->get (SLP_TREE_SCALAR_STMTS (node)))
{
SLP_TREE_VEC_STMTS (node).safe_splice (SLP_TREE_VEC_STMTS (*leader));
return;
}
bst_map->put (SLP_TREE_SCALAR_STMTS (node).copy (), node);
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child) FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
vect_schedule_slp_instance (child, instance, bst_map); vect_schedule_slp_instance (child, instance);
/* Push SLP node def-type to stmts. */ /* Push SLP node def-type to stmts. */
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child) FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
...@@ -4376,14 +4352,12 @@ vect_schedule_slp (vec_info *vinfo) ...@@ -4376,14 +4352,12 @@ vect_schedule_slp (vec_info *vinfo)
slp_instance instance; slp_instance instance;
unsigned int i; unsigned int i;
scalar_stmts_to_slp_tree_map_t *bst_map
= new scalar_stmts_to_slp_tree_map_t ();
slp_instances = vinfo->slp_instances; slp_instances = vinfo->slp_instances;
FOR_EACH_VEC_ELT (slp_instances, i, instance) FOR_EACH_VEC_ELT (slp_instances, i, instance)
{ {
slp_tree node = SLP_INSTANCE_TREE (instance); slp_tree node = SLP_INSTANCE_TREE (instance);
/* Schedule the tree of INSTANCE. */ /* Schedule the tree of INSTANCE. */
vect_schedule_slp_instance (node, instance, bst_map); vect_schedule_slp_instance (node, instance);
if (SLP_INSTANCE_ROOT_STMT (instance)) if (SLP_INSTANCE_ROOT_STMT (instance))
vectorize_slp_instance_root_stmt (node, instance); vectorize_slp_instance_root_stmt (node, instance);
...@@ -4392,7 +4366,6 @@ vect_schedule_slp (vec_info *vinfo) ...@@ -4392,7 +4366,6 @@ vect_schedule_slp (vec_info *vinfo)
dump_printf_loc (MSG_NOTE, vect_location, dump_printf_loc (MSG_NOTE, vect_location,
"vectorizing stmts using SLP.\n"); "vectorizing stmts using SLP.\n");
} }
delete bst_map;
FOR_EACH_VEC_ELT (slp_instances, i, instance) FOR_EACH_VEC_ELT (slp_instances, i, instance)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment