We have to check each operand for being in a pattern, not just the
first when avoiding build from scalars (we could possibly handle
the special case of some of them being the pattern stmt root, but
that would be a followup improvement).

Bootstrap & regtest running on x86-64-unknown-linux-gnu.

Richard.

2019-10-25  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/92222
        * tree-vect-slp.c (_slp_oprnd_info::first_pattern): Remove.
        (_slp_oprnd_info::second_pattern): Likewise.
        (_slp_oprnd_info::any_pattern): New.
        (vect_create_oprnd_info): Adjust.
        (vect_get_and_check_slp_defs): Compute whether any stmt is
        in a pattern.
        (vect_build_slp_tree_2): Avoid building up a node from scalars
        if any of the operand defs, not just the first, is in a pattern.

        * gcc.dg/torture/pr92222.c: New testcase.

Index: gcc/tree-vect-slp.c
===================================================================
--- gcc/tree-vect-slp.c (revision 277441)
+++ gcc/tree-vect-slp.c (working copy)
@@ -177,8 +177,7 @@ typedef struct _slp_oprnd_info
      stmt.  */
   tree first_op_type;
   enum vect_def_type first_dt;
-  bool first_pattern;
-  bool second_pattern;
+  bool any_pattern;
 } *slp_oprnd_info;
 
 
@@ -199,8 +198,7 @@ vect_create_oprnd_info (int nops, int gr
       oprnd_info->ops.create (group_size);
       oprnd_info->first_dt = vect_uninitialized_def;
       oprnd_info->first_op_type = NULL_TREE;
-      oprnd_info->first_pattern = false;
-      oprnd_info->second_pattern = false;
+      oprnd_info->any_pattern = false;
       oprnds_info.quick_push (oprnd_info);
     }
 
@@ -339,13 +337,11 @@ vect_get_and_check_slp_defs (vec_info *v
   tree oprnd;
   unsigned int i, number_of_oprnds;
   enum vect_def_type dt = vect_uninitialized_def;
-  bool pattern = false;
   slp_oprnd_info oprnd_info;
   int first_op_idx = 1;
   unsigned int commutative_op = -1U;
   bool first_op_cond = false;
   bool first = stmt_num == 0;
-  bool second = stmt_num == 1;
 
   if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
     {
@@ -418,13 +414,12 @@ again:
          return -1;
        }
 
-      if (second)
-       oprnd_info->second_pattern = pattern;
+      if (def_stmt_info && is_pattern_stmt_p (def_stmt_info))
+       oprnd_info->any_pattern = true;
 
       if (first)
        {
          oprnd_info->first_dt = dt;
-         oprnd_info->first_pattern = pattern;
          oprnd_info->first_op_type = TREE_TYPE (oprnd);
        }
       else
@@ -1311,7 +1306,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
              /* ???  Rejecting patterns this way doesn't work.  We'd have to
                 do extra work to cancel the pattern so the uses see the
                 scalar version.  */
-             && !is_pattern_stmt_p (SLP_TREE_SCALAR_STMTS (child)[0]))
+             && !oprnd_info->any_pattern)
            {
              slp_tree grandchild;
 
@@ -1358,18 +1353,16 @@ vect_build_slp_tree_2 (vec_info *vinfo,
          /* ???  Rejecting patterns this way doesn't work.  We'd have to
             do extra work to cancel the pattern so the uses see the
             scalar version.  */
-         && !is_pattern_stmt_p (stmt_info))
+         && !is_pattern_stmt_p (stmt_info)
+         && !oprnd_info->any_pattern)
        {
          if (dump_enabled_p ())
            dump_printf_loc (MSG_NOTE, vect_location,
                             "Building vector operands from scalars\n");
          this_tree_size++;
-         child = vect_create_new_slp_node (oprnd_info->def_stmts);
-         SLP_TREE_DEF_TYPE (child) = vect_external_def;
-         SLP_TREE_SCALAR_OPS (child) = oprnd_info->ops;
+         child = vect_create_new_slp_node (oprnd_info->ops);
          children.safe_push (child);
          oprnd_info->ops = vNULL;
-         oprnd_info->def_stmts = vNULL;
          continue;
        }
 
@@ -1469,7 +1440,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
                  /* ???  Rejecting patterns this way doesn't work.  We'd have
                     to do extra work to cancel the pattern so the uses see the
                     scalar version.  */
-                 && !is_pattern_stmt_p (SLP_TREE_SCALAR_STMTS (child)[0]))
+                 && !oprnd_info->any_pattern)
                {
                  unsigned int j;
                  slp_tree grandchild;
Index: gcc/testsuite/gcc.dg/torture/pr92222.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr92222.c      (nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr92222.c      (working copy)
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-ftree-vectorize" } */
+
+unsigned char *a;
+int b;
+void f();
+void c()
+{
+  char *d;
+  int e;
+  for (; b; b++) {
+      e = 7;
+      for (; e >= 0; e--)
+       *d++ = a[b] & 1 << e ? '1' : '0';
+  }
+  f();
+}

Reply via email to