382 lines
13 KiB
Diff
382 lines
13 KiB
Diff
|
|
This backport contains 1 patch from gcc main stream tree.
|
||
|
|
The commit id of these patchs list as following in the order of time.
|
||
|
|
|
||
|
|
0001-re-PR-tree-optimization-92516-ICE-in-vect_schedule_s.patch
|
||
|
|
10a73df76280e12886cb20b028727436d73724c5
|
||
|
|
|
||
|
|
diff -Nurp a/gcc/testsuite/gcc.dg/vect/vect-ctor-1.c b/gcc/testsuite/gcc.dg/vect/vect-ctor-1.c
|
||
|
|
--- a/gcc/testsuite/gcc.dg/vect/vect-ctor-1.c 1970-01-01 08:00:00.000000000 +0800
|
||
|
|
+++ b/gcc/testsuite/gcc.dg/vect/vect-ctor-1.c 2020-08-17 10:33:56.052000000 +0800
|
||
|
|
@@ -0,0 +1,17 @@
|
||
|
|
+/* { 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;
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
diff -Nurp a/gcc/testsuite/g++.dg/vect/slp-pr92516.cc b/gcc/testsuite/g++.dg/vect/slp-pr92516.cc
|
||
|
|
--- a/gcc/testsuite/g++.dg/vect/slp-pr92516.cc 1970-01-01 08:00:00.000000000 +0800
|
||
|
|
+++ b/gcc/testsuite/g++.dg/vect/slp-pr92516.cc 2020-08-17 10:33:56.052000000 +0800
|
||
|
|
@@ -0,0 +1,43 @@
|
||
|
|
+// { 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;
|
||
|
|
+}
|
||
|
|
diff -Nurp a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
|
||
|
|
--- a/gcc/tree-vect-slp.c 2020-08-17 10:31:58.236000000 +0800
|
||
|
|
+++ b/gcc/tree-vect-slp.c 2020-08-17 10:36:40.976796520 +0800
|
||
|
|
@@ -2010,6 +2010,7 @@ calculate_unrolling_factor (poly_uint64
|
||
|
|
|
||
|
|
static bool
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
slp_instance new_instance;
|
||
|
|
@@ -2117,19 +2118,11 @@ vect_analyze_slp_instance (vec_info *vin
|
||
|
|
/* Build the tree for the SLP instance. */
|
||
|
|
bool *matches = XALLOCAVEC (bool, group_size);
|
||
|
|
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;
|
||
|
|
unsigned tree_size = 0;
|
||
|
|
node = vect_build_slp_tree (vinfo, scalar_stmts, group_size,
|
||
|
|
&max_nunits, matches, &npermutes,
|
||
|
|
&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 this is a reduction chain with a conversion in front
|
||
|
|
@@ -2183,6 +2176,18 @@ vect_analyze_slp_instance (vec_info *vin
|
||
|
|
matches[group_size / const_max_nunits * const_max_nunits] = 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
|
||
|
|
{
|
||
|
|
/* Create a new SLP instance. */
|
||
|
|
@@ -2317,7 +2322,7 @@ vect_analyze_slp_instance (vec_info *vin
|
||
|
|
|
||
|
|
stmt_vec_info rest = vect_split_slp_store_group (stmt_info,
|
||
|
|
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);
|
||
|
|
/* If the first non-match was in the middle of a vector,
|
||
|
|
skip the rest of that vector. */
|
||
|
|
@@ -2328,7 +2333,8 @@ vect_analyze_slp_instance (vec_info *vin
|
||
|
|
rest = vect_split_slp_store_group (rest, const_nunits);
|
||
|
|
}
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
/* Even though the first vector did not all match, we might be able to SLP
|
||
|
|
@@ -2350,9 +2356,12 @@ vect_analyze_slp (vec_info *vinfo, unsig
|
||
|
|
|
||
|
|
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. */
|
||
|
|
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))
|
||
|
|
{
|
||
|
|
@@ -2361,7 +2370,7 @@ vect_analyze_slp (vec_info *vinfo, unsig
|
||
|
|
{
|
||
|
|
/* Find SLP sequences starting from reduction chains. */
|
||
|
|
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))
|
||
|
|
{
|
||
|
|
/* Dissolve reduction chain group. */
|
||
|
|
@@ -2383,10 +2392,17 @@ vect_analyze_slp (vec_info *vinfo, unsig
|
||
|
|
|
||
|
|
/* Find SLP sequences starting from groups of reductions. */
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
|
||
|
|
+ /* 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 ();
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -2513,13 +2529,6 @@ vect_detect_hybrid_slp_stmts (slp_tree n
|
||
|
|
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. */
|
||
|
|
|
||
|
|
static tree
|
||
|
|
@@ -2602,11 +2611,12 @@ vect_detect_hybrid_slp (loop_vec_info lo
|
||
|
|
/* Then walk the SLP instance trees marking stmts with uses in
|
||
|
|
non-SLP stmts as hybrid, also propagating hybrid down the
|
||
|
|
SLP tree, collecting the above info on-the-fly. */
|
||
|
|
+ hash_map<slp_tree, unsigned> visited;
|
||
|
|
FOR_EACH_VEC_ELT (slp_instances, i, instance)
|
||
|
|
{
|
||
|
|
for (unsigned i = 0; i < SLP_INSTANCE_GROUP_SIZE (instance); ++i)
|
||
|
|
vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance),
|
||
|
|
- i, pure_slp);
|
||
|
|
+ i, pure_slp, visited);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -2763,8 +2773,8 @@ vect_slp_convert_to_external (vec_info *
|
||
|
|
static bool
|
||
|
|
vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
|
||
|
|
slp_instance node_instance,
|
||
|
|
- scalar_stmts_to_slp_tree_map_t *visited,
|
||
|
|
- scalar_stmts_to_slp_tree_map_t *lvisited,
|
||
|
|
+ hash_set<slp_tree> &visited,
|
||
|
|
+ hash_set<slp_tree> &lvisited,
|
||
|
|
stmt_vector_for_cost *cost_vec)
|
||
|
|
{
|
||
|
|
int i, j;
|
||
|
|
@@ -2774,27 +2784,13 @@ vect_slp_analyze_node_operations (vec_in
|
||
|
|
return true;
|
||
|
|
|
||
|
|
/* If we already analyzed the exact same set of scalar stmts we're done.
|
||
|
|
- We share the generated vector stmts for those. */
|
||
|
|
- slp_tree *leader;
|
||
|
|
- 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
|
||
|
|
+ We share the generated vector stmts for those.
|
||
|
|
+ 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
|
||
|
|
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)
|
||
|
|
if (!vect_slp_analyze_node_operations (vinfo, child, node_instance,
|
||
|
|
@@ -2867,16 +2863,15 @@ vect_slp_analyze_operations (vec_info *v
|
||
|
|
|
||
|
|
DUMP_VECT_SCOPE ("vect_slp_analyze_operations");
|
||
|
|
|
||
|
|
- scalar_stmts_to_slp_tree_map_t *visited
|
||
|
|
- = new scalar_stmts_to_slp_tree_map_t ();
|
||
|
|
+ hash_set<slp_tree> visited;
|
||
|
|
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;
|
||
|
|
cost_vec.create (2);
|
||
|
|
if (!vect_slp_analyze_node_operations (vinfo,
|
||
|
|
SLP_INSTANCE_TREE (instance),
|
||
|
|
- instance, visited, &lvisited,
|
||
|
|
+ instance, visited, lvisited,
|
||
|
|
&cost_vec))
|
||
|
|
{
|
||
|
|
slp_tree node = SLP_INSTANCE_TREE (instance);
|
||
|
|
@@ -2891,16 +2886,15 @@ vect_slp_analyze_operations (vec_info *v
|
||
|
|
}
|
||
|
|
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)
|
||
|
|
- visited->put ((*x).first.copy (), (*x).second);
|
||
|
|
+ visited.add (*x);
|
||
|
|
i++;
|
||
|
|
|
||
|
|
add_stmt_costs (vinfo->target_cost_data, &cost_vec);
|
||
|
|
cost_vec.release ();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
- delete visited;
|
||
|
|
|
||
|
|
return !vinfo->slp_instances.is_empty ();
|
||
|
|
}
|
||
|
|
@@ -2991,15 +2985,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. */
|
||
|
|
|
||
|
|
static bool
|
||
|
|
@@ -3014,13 +2999,14 @@ vect_bb_vectorization_profitable_p (bb_v
|
||
|
|
/* Calculate scalar cost. */
|
||
|
|
stmt_vector_for_cost scalar_costs;
|
||
|
|
scalar_costs.create (0);
|
||
|
|
+ hash_set<slp_tree> visited;
|
||
|
|
FOR_EACH_VEC_ELT (slp_instances, i, instance)
|
||
|
|
{
|
||
|
|
auto_vec<bool, 20> life;
|
||
|
|
life.safe_grow_cleared (SLP_INSTANCE_GROUP_SIZE (instance));
|
||
|
|
vect_bb_slp_scalar_cost (BB_VINFO_BB (bb_vinfo),
|
||
|
|
SLP_INSTANCE_TREE (instance),
|
||
|
|
- &life, &scalar_costs);
|
||
|
|
+ &life, &scalar_costs, visited);
|
||
|
|
}
|
||
|
|
void *target_cost_data = init_cost (NULL);
|
||
|
|
add_stmt_costs (target_cost_data, &scalar_costs);
|
||
|
|
@@ -4052,8 +4038,7 @@ vect_transform_slp_perm_load (slp_tree n
|
||
|
|
/* Vectorize SLP instance tree in postorder. */
|
||
|
|
|
||
|
|
static void
|
||
|
|
-vect_schedule_slp_instance (slp_tree node, slp_instance instance,
|
||
|
|
- scalar_stmts_to_slp_tree_map_t *bst_map)
|
||
|
|
+vect_schedule_slp_instance (slp_tree node, slp_instance instance)
|
||
|
|
{
|
||
|
|
gimple_stmt_iterator si;
|
||
|
|
stmt_vec_info stmt_info;
|
||
|
|
@@ -4070,17 +4055,8 @@ vect_schedule_slp_instance (slp_tree nod
|
||
|
|
if (SLP_TREE_VEC_STMTS (node).exists ())
|
||
|
|
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)
|
||
|
|
- vect_schedule_slp_instance (child, instance, bst_map);
|
||
|
|
+ vect_schedule_slp_instance (child, instance);
|
||
|
|
|
||
|
|
/* Push SLP node def-type to stmts. */
|
||
|
|
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
|
||
|
|
@@ -4297,14 +4273,12 @@ vect_schedule_slp (vec_info *vinfo)
|
||
|
|
slp_instance instance;
|
||
|
|
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;
|
||
|
|
FOR_EACH_VEC_ELT (slp_instances, i, instance)
|
||
|
|
{
|
||
|
|
slp_tree node = SLP_INSTANCE_TREE (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))
|
||
|
|
vectorize_slp_instance_root_stmt (node, instance);
|
||
|
|
@@ -4313,7 +4287,6 @@ vect_schedule_slp (vec_info *vinfo)
|
||
|
|
dump_printf_loc (MSG_NOTE, vect_location,
|
||
|
|
"vectorizing stmts using SLP.\n");
|
||
|
|
}
|
||
|
|
- delete bst_map;
|
||
|
|
|
||
|
|
FOR_EACH_VEC_ELT (slp_instances, i, instance)
|
||
|
|
{
|