tree-optimization/95272 - add SLP_TREE_REPRESENTATIVE
authorRichard Biener <rguenther@suse.de>
Fri, 29 May 2020 10:00:00 +0000 (12:00 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 29 May 2020 11:00:36 +0000 (13:00 +0200)
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.

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 [new file with mode: 0644]
gcc/tree-vect-loop.c
gcc/tree-vect-slp.c
gcc/tree-vectorizer.h

diff --git a/gcc/testsuite/gcc.dg/vect/pr95272.c b/gcc/testsuite/gcc.dg/vect/pr95272.c
new file mode 100644 (file)
index 0000000..47698ff
--- /dev/null
@@ -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];
+  }
+}
index 4f94b4baad9f7c50eeecbe3a1deb0c6036a9e599..3c5c0ea9ebcf853729886d5cbf15688b7a86784c 100644 (file)
@@ -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);
index 5976e91cf6247a5048797d5d636e77aa8fffe0d3..836defce9901683b000216f98c809451c7c82c5d 100644 (file)
@@ -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);
index 2bde71760e53c9034b15ba868bb6f0aac43d6a5b..5a5648b37847c94334219717f4ca53720200db73 100644 (file)
@@ -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