re PR tree-optimization/61634 (ICE in in vect_get_vec_def_for_operand, at tree-vect...
authorRichard Biener <rguenther@suse.de>
Thu, 27 Nov 2014 09:33:32 +0000 (09:33 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 27 Nov 2014 09:33:32 +0000 (09:33 +0000)
2014-11-27  Richard Biener  <rguenther@suse.de>

PR tree-optimization/61634
* tree-vect-slp.c: Include gimple-walk.h.
(vect_detect_hybrid_slp_stmts): Rewrite to propagate hybrid
down the SLP tree for one scalar statement.
(vect_detect_hybrid_slp_1): New walker function.
(vect_detect_hybrid_slp_2): Likewise.
(vect_detect_hybrid_slp): Properly handle pattern statements
in a pre-scan over all loop stmts.

* gcc.dg/vect/pr61634.c: New testcase.

From-SVN: r218113

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/pr61634.c [new file with mode: 0644]
gcc/tree-vect-slp.c

index 515128f07ecf6f381f3b9c6838831067e6bef45e..26b4720c8580b62e688ee5adddfe8c75151cd353 100644 (file)
@@ -1,3 +1,14 @@
+2014-11-27  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/61634
+       * tree-vect-slp.c: Include gimple-walk.h.
+       (vect_detect_hybrid_slp_stmts): Rewrite to propagate hybrid
+       down the SLP tree for one scalar statement.
+       (vect_detect_hybrid_slp_1): New walker function.
+       (vect_detect_hybrid_slp_2): Likewise.
+       (vect_detect_hybrid_slp): Properly handle pattern statements
+       in a pre-scan over all loop stmts.
+
 2014-11-27  Zhenqiang Chen  <zhenqiang.chen@linaro.org>
 
        Revert:
index b96e698c0d6eb7e4409d0a8e10585acd9740cbf3..5e671fa92fef85435c1ea41a4e2abb5435208f37 100644 (file)
@@ -1,3 +1,8 @@
+2014-11-27  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/61634
+       * gcc.dg/vect/pr61634.c: New testcase.
+
 2014-11-26  David Edelsohn  <dje.gcc@gmail.com>
 
        * g++.dg/ext/alignof2.C: xfail-run-if on AIX.
diff --git a/gcc/testsuite/gcc.dg/vect/pr61634.c b/gcc/testsuite/gcc.dg/vect/pr61634.c
new file mode 100644 (file)
index 0000000..80b2c3a
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+
+int a, b, c, d;
+short *e;
+void fn1 (int p1[], int p2, int p3[], int p4[], int p5[], int *p6)
+{
+  int f;
+  c = *p1;
+  d = *p5;
+  (void)p6;
+  for (; a; a--)
+    {
+      f = *e >> 2;
+      *e++ = f;
+      b += f * f;
+      f = *e >> 2;
+      *e++ = f;
+    }
+  p4[0] = p3[0];
+  for (;; p2--)
+    ;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
index 829f74aaea80a0f024ab0afda1f2b094280fe90a..270423df5848fa8bac27da3e03c1001cb98c28aa 100644 (file)
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "optabs.h"
 #include "tree-vectorizer.h"
 #include "langhooks.h"
+#include "gimple-walk.h"
 
 /* Extract the location of the basic block in the source code.
    Return the basic block location if succeed and NULL if not.  */
@@ -1829,51 +1830,83 @@ vect_make_slp_decision (loop_vec_info loop_vinfo)
    can't be SLPed) in the tree rooted at NODE.  Mark such stmts as HYBRID.  */
 
 static void
-vect_detect_hybrid_slp_stmts (slp_tree node)
+vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype)
 {
-  int i;
-  vec<gimple> stmts = SLP_TREE_SCALAR_STMTS (node);
-  gimple stmt = stmts[0];
+  gimple stmt = SLP_TREE_SCALAR_STMTS (node)[i];
   imm_use_iterator imm_iter;
   gimple use_stmt;
-  stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+  stmt_vec_info use_vinfo, stmt_vinfo = vinfo_for_stmt (stmt);
   slp_tree child;
   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
-  struct loop *loop = NULL;
-  bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
-  basic_block bb = NULL;
+  struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+  int j;
+
+  /* Propagate hybrid down the SLP tree.  */
+  if (stype == hybrid)
+    ;
+  else if (HYBRID_SLP_STMT (stmt_vinfo))
+    stype = hybrid;
+  else
+    {
+      /* Check if a pure SLP stmt has uses in non-SLP stmts.  */
+      gcc_checking_assert (PURE_SLP_STMT (stmt_vinfo));
+      if (TREE_CODE (gimple_op (stmt, 0)) == SSA_NAME)
+       FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, gimple_op (stmt, 0))
+         if (gimple_bb (use_stmt)
+             && flow_bb_inside_loop_p (loop, gimple_bb (use_stmt))
+             && (use_vinfo = vinfo_for_stmt (use_stmt))
+             && !STMT_SLP_TYPE (use_vinfo)
+             && (STMT_VINFO_RELEVANT (use_vinfo)
+                 || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (use_vinfo))
+                 || (STMT_VINFO_IN_PATTERN_P (use_vinfo)
+                     && STMT_VINFO_RELATED_STMT (use_vinfo)
+                     && !STMT_SLP_TYPE (vinfo_for_stmt
+                           (STMT_VINFO_RELATED_STMT (use_vinfo)))))
+             && !(gimple_code (use_stmt) == GIMPLE_PHI
+                  && STMT_VINFO_DEF_TYPE (use_vinfo) == vect_reduction_def))
+           stype = hybrid;
+    }
+
+  if (stype == hybrid)
+    STMT_SLP_TYPE (stmt_vinfo) = hybrid;
+
+  FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
+    vect_detect_hybrid_slp_stmts (child, i, stype);
+}
 
-  if (!node)
-    return;
+/* Helpers for vect_detect_hybrid_slp walking pattern stmt uses.  */
 
-  if (loop_vinfo)
-    loop = LOOP_VINFO_LOOP (loop_vinfo);
-  else
-    bb = BB_VINFO_BB (bb_vinfo);
+static tree
+vect_detect_hybrid_slp_1 (tree *tp, int *, void *data)
+{
+  walk_stmt_info *wi = (walk_stmt_info *)data;
+  struct loop *loopp = (struct loop *)wi->info;
 
-  FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
-    if (PURE_SLP_STMT (vinfo_for_stmt (stmt))
-       && TREE_CODE (gimple_op (stmt, 0)) == SSA_NAME)
-      FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, gimple_op (stmt, 0))
-       if (gimple_bb (use_stmt)
-            && ((loop && flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)))
-                || bb == gimple_bb (use_stmt))
-           && (stmt_vinfo = vinfo_for_stmt (use_stmt))
-           && !STMT_SLP_TYPE (stmt_vinfo)
-            && (STMT_VINFO_RELEVANT (stmt_vinfo)
-                || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_vinfo))
-               || (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)
-                   && STMT_VINFO_RELATED_STMT (stmt_vinfo)
-                   && !STMT_SLP_TYPE (vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_vinfo)))))
-           && !(gimple_code (use_stmt) == GIMPLE_PHI
-                 && STMT_VINFO_DEF_TYPE (stmt_vinfo)
-                  == vect_reduction_def))
-         vect_mark_slp_stmts (node, hybrid, i);
+  if (wi->is_lhs)
+    return NULL_TREE;
 
-  FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
-    vect_detect_hybrid_slp_stmts (child);
+  if (TREE_CODE (*tp) == SSA_NAME
+      && !SSA_NAME_IS_DEFAULT_DEF (*tp))
+    {
+      gimple def_stmt = SSA_NAME_DEF_STMT (*tp);
+      if (flow_bb_inside_loop_p (loopp, gimple_bb (def_stmt))
+         && PURE_SLP_STMT (vinfo_for_stmt (def_stmt)))
+       STMT_SLP_TYPE (vinfo_for_stmt (def_stmt)) = hybrid;
+    }
+
+  return NULL_TREE;
 }
 
+static tree
+vect_detect_hybrid_slp_2 (gimple_stmt_iterator *gsi, bool *handled,
+                         walk_stmt_info *)
+{
+  /* If the stmt is in a SLP instance then this isn't a reason
+     to mark use definitions in other SLP instances as hybrid.  */
+  if (STMT_SLP_TYPE (vinfo_for_stmt (gsi_stmt (*gsi))) != loop_vect)
+    *handled = true;
+  return NULL_TREE;
+}
 
 /* Find stmts that must be both vectorized and SLPed.  */
 
@@ -1888,8 +1921,41 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
     dump_printf_loc (MSG_NOTE, vect_location, "=== vect_detect_hybrid_slp ==="
                      "\n");
 
+  /* First walk all pattern stmt in the loop and mark defs of uses as
+     hybrid because immediate uses in them are not recorded.  */
+  for (i = 0; i < LOOP_VINFO_LOOP (loop_vinfo)->num_nodes; ++i)
+    {
+      basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i];
+      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+          gsi_next (&gsi))
+       {
+         gimple stmt = gsi_stmt (gsi);
+         stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+         if (STMT_VINFO_IN_PATTERN_P (stmt_info))
+           {
+             walk_stmt_info wi;
+             memset (&wi, 0, sizeof (wi));
+             wi.info = LOOP_VINFO_LOOP (loop_vinfo);
+             gimple_stmt_iterator gsi2
+               = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
+             walk_gimple_stmt (&gsi2, vect_detect_hybrid_slp_2,
+                               vect_detect_hybrid_slp_1, &wi);
+             walk_gimple_seq (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
+                              vect_detect_hybrid_slp_2,
+                              vect_detect_hybrid_slp_1, &wi);
+           }
+       }
+    }
+
+  /* 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.  */
   FOR_EACH_VEC_ELT (slp_instances, i, instance)
-    vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance));
+    {
+      for (unsigned i = 0; i < SLP_INSTANCE_GROUP_SIZE (instance); ++i)
+       vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance),
+                                     i, pure_slp);
+    }
 }