tree-optimization/95272 - add SLP_TREE_REPRESENTATIVE

Message ID nycvar.YFH.7.76.2005291259590.4397@zhemvz.fhfr.qr
State New
Headers show
Series
  • tree-optimization/95272 - add SLP_TREE_REPRESENTATIVE
Related show

Commit Message

Richard Biener May 29, 2020, 11 a.m.
This adds SLP_TREE_REPRESENTATIVE - a representative stmt-info that
is used by SLP analysis and code generation.  This avoids the need
for the hack in vect_slp_rearrange_stmts which previously avoided
to re-arrange stmts that might not have been isomorphic because
of operand swapping.  It also plays nice with future directions of SLP
and for the forseeable future is easier than replicating more and
more info in the SLP node as long as non-SLP is in-tree.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2020-05-29  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/95272
	* tree-vectorizer.h (_slp_tree::representative): Add.
	(SLP_TREE_REPRESENTATIVE): Likewise.
	* tree-vect-loop.c (vectorizable_reduction): Adjust SLP
	node gathering.
	(vectorizable_live_operation): Use the representative to
	attach the reduction info to.
	* tree-vect-slp.c (_slp_tree::_slp_tree): Initialize
	SLP_TREE_REPRESENTATIVE.
	(vect_create_new_slp_node): Likewise.
	(slp_copy_subtree): Copy it.
	(vect_slp_rearrange_stmts): Re-arrange even COND_EXPR stmts.
	(vect_slp_analyze_node_operations_1): Pass the representative
	to vect_analyze_stmt.
	(vect_schedule_slp_instance): Pass the representative to
	vect_transform_stmt.

	* gcc.dg/vect/pr95272.c: New testcase.
---
 gcc/testsuite/gcc.dg/vect/pr95272.c | 18 ++++++++++++++++++
 gcc/tree-vect-loop.c                |  8 ++++++--
 gcc/tree-vect-slp.c                 | 15 +++++----------
 gcc/tree-vectorizer.h               |  4 ++++
 4 files changed, 33 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr95272.c

-- 
2.26.2

Patch

diff --git a/gcc/testsuite/gcc.dg/vect/pr95272.c b/gcc/testsuite/gcc.dg/vect/pr95272.c
new file mode 100644
index 00000000000..47698ff3e56
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr95272.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+
+enum { a = 5, b };
+typedef struct {
+  int c[b];
+} d;
+extern d e[];
+int f;
+int g[6];
+void h() {
+  int i;
+  for (; f; f++) {
+    i = 0;
+    for (; i < b; i++)
+      if (e[f].c[i])
+        g[i] = e[f].c[i];
+  }
+}
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 4f94b4baad9..3c5c0ea9ebc 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -6192,9 +6192,9 @@  vectorizable_reduction (loop_vec_info loop_vinfo,
     {
       slp_for_stmt_info = slp_node_instance->root;
       /* And then there's reduction chain with a conversion ...  */
-      if (SLP_TREE_SCALAR_STMTS (slp_for_stmt_info)[0] != stmt_info)
+      if (SLP_TREE_REPRESENTATIVE (slp_for_stmt_info) != stmt_info)
 	slp_for_stmt_info = SLP_TREE_CHILDREN (slp_for_stmt_info)[0];
-      gcc_assert (SLP_TREE_SCALAR_STMTS (slp_for_stmt_info)[0] == stmt_info);
+      gcc_assert (SLP_TREE_REPRESENTATIVE (slp_for_stmt_info) == stmt_info);
     }
   slp_tree *slp_op = XALLOCAVEC (slp_tree, op_type);
   for (i = 0; i < op_type; i++)
@@ -7952,6 +7952,10 @@  vectorizable_live_operation (loop_vec_info loop_vinfo,
 	     all involved stmts together.  */
 	  else if (slp_index != 0)
 	    return true;
+	  else
+	    /* For SLP reductions the meta-info is attached to
+	       the representative.  */
+	    stmt_info = SLP_TREE_REPRESENTATIVE (slp_node);
 	}
       stmt_vec_info reduc_info = info_for_reduction (loop_vinfo, stmt_info);
       gcc_assert (reduc_info->is_reduc_info);
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 5976e91cf62..836defce990 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -61,6 +61,7 @@  _slp_tree::_slp_tree ()
   SLP_TREE_TWO_OPERATORS (this) = false;
   SLP_TREE_DEF_TYPE (this) = vect_uninitialized_def;
   SLP_TREE_VECTYPE (this) = NULL_TREE;
+  SLP_TREE_REPRESENTATIVE (this) = NULL;
   this->refcnt = 1;
   this->max_nunits = 1;
 }
@@ -132,6 +133,7 @@  vect_create_new_slp_node (vec<stmt_vec_info> scalar_stmts, unsigned nops)
   SLP_TREE_SCALAR_STMTS (node) = scalar_stmts;
   SLP_TREE_CHILDREN (node).create (nops);
   SLP_TREE_DEF_TYPE (node) = vect_internal_def;
+  SLP_TREE_REPRESENTATIVE (node) = scalar_stmts[0];
 
   unsigned i;
   stmt_vec_info stmt_info;
@@ -1741,6 +1743,7 @@  slp_copy_subtree (slp_tree node, hash_map<slp_tree, slp_tree> &map)
   slp_tree copy = copy_ref;
   SLP_TREE_DEF_TYPE (copy) = SLP_TREE_DEF_TYPE (node);
   SLP_TREE_VECTYPE (copy) = SLP_TREE_VECTYPE (node);
+  SLP_TREE_REPRESENTATIVE (copy) = SLP_TREE_REPRESENTATIVE (node);
   copy->max_nunits = node->max_nunits;
   copy->refcnt = 0;
   if (SLP_TREE_SCALAR_STMTS (node).exists ())
@@ -1786,14 +1789,6 @@  vect_slp_rearrange_stmts (slp_tree node, unsigned int group_size,
   if (SLP_TREE_SCALAR_STMTS (node).exists ())
     {
       gcc_assert (group_size == SLP_TREE_SCALAR_STMTS (node).length ());
-      /* ???  Computation nodes are isomorphic and need no rearrangement.
-	 This is a quick hack to cover those where rearrangement breaks
-	 semantics because only the first stmt is guaranteed to have the
-	 correct operation code due to others being swapped or inverted.  */
-      stmt_vec_info first = SLP_TREE_SCALAR_STMTS (node)[0];
-      if (is_gimple_assign (first->stmt)
-	  && gimple_assign_rhs_code (first->stmt) == COND_EXPR)
-	return;
       vec<stmt_vec_info> tmp_stmts;
       tmp_stmts.create (group_size);
       tmp_stmts.quick_grow (group_size);
@@ -2664,7 +2659,7 @@  vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
 				    slp_instance node_instance,
 				    stmt_vector_for_cost *cost_vec)
 {
-  stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
+  stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node);
   gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
 
   /* Calculate the number of vector statements to be created for the
@@ -4079,7 +4074,7 @@  vect_schedule_slp_instance (vec_info *vinfo,
 	  STMT_VINFO_DEF_TYPE (child_stmt_info) = SLP_TREE_DEF_TYPE (child);
       }
 
-  stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
+  stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node);
 
   /* VECTYPE is the type of the destination.  */
   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 2bde71760e5..5a5648b3784 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -128,6 +128,9 @@  struct _slp_tree {
   vec<stmt_vec_info> stmts;
   /* A group of scalar operands to be vectorized together.  */
   vec<tree> ops;
+  /* The representative that should be used for analysis and
+     code generation.  */
+  stmt_vec_info representative;
 
   /* Load permutation relative to the stores, NULL if there is no
      permutation.  */
@@ -193,6 +196,7 @@  public:
 #define SLP_TREE_TWO_OPERATORS(S)		 (S)->two_operators
 #define SLP_TREE_DEF_TYPE(S)			 (S)->def_type
 #define SLP_TREE_VECTYPE(S)			 (S)->vectype
+#define SLP_TREE_REPRESENTATIVE(S)		 (S)->representative
 
 /* Key for map that records association between
    scalar conditions and corresponding loop mask, and