re PR tree-optimization/64746 (Loop with nested load/stores is not vectorized using...
authorYuri Rumyantsev <ysrumyan@gmail.com>
Thu, 29 Jan 2015 13:52:28 +0000 (13:52 +0000)
committerIlya Enkovich <ienkovich@gcc.gnu.org>
Thu, 29 Jan 2015 13:52:28 +0000 (13:52 +0000)
gcc/

PR tree-optimization/64746
* tree-if-conv.c (mask_exists): New function.
(predicate_mem_writes): Save created mask with given size for further
use.
(stmt_is_root_of_bool_pattern): Remove argument VAR and store to it.
(ifcvt_repair_bool_pattern): Collect all statements that are root
of bool pattern and use iterative algorithm to remove multiple uses
of predicates, display number of required iterations.

gcc/testsuite/

PR tree-optimization/64746
* gcc.target/i386/avx2-vect-aggressive-1.c: New test.

From-SVN: r220248

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c [new file with mode: 0644]
gcc/tree-if-conv.c

index be590e5aa991edad0cc86e7794b55dca249d0d67..7424d9faa42cb7e2da21b11d419e3813ad05f0cc 100644 (file)
@@ -1,3 +1,14 @@
+2015-01-29  Yuri Rumyantsev  <ysrumyan@gmail.com>
+
+       PR tree-optimization/64746
+       * tree-if-conv.c (mask_exists): New function.
+       (predicate_mem_writes): Save created mask with given size for further
+       use.
+       (stmt_is_root_of_bool_pattern): Remove argument VAR and store to it.
+       (ifcvt_repair_bool_pattern): Collect all statements that are root
+       of bool pattern and use iterative algorithm to remove multiple uses
+       of predicates, display number of required iterations.
+
 2015-01-29  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/64853
index 8409b469634f02814f4d91749b9e6059fb9946c0..69488ec0106a01c2aa7fb5c02cf7957aaa9affec 100644 (file)
@@ -1,3 +1,8 @@
+2015-01-29  Yuri Rumyantsev  <ysrumyan@gmail.com>
+
+       PR tree-optimization/64746
+       * gcc.target/i386/avx2-vect-aggressive-1.c: New test.
+
 2015-01-29  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/64853
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c b/gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c
new file mode 100644 (file)
index 0000000..a9a88e1
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-options "-mavx2 -O3 -fopenmp-simd -fdump-tree-vect-details" } */
+
+#define N 256
+int a1[N], a2[N], a3[N], a4[N], a5[N], a6[N], a7[N];
+
+void foo()
+{
+  int x1, x2, x3;
+  int i;
+#pragma omp simd safelen(8)
+  for (i=0; i<N; i++)
+    {
+      x1 = a1[i] + a2 [i];
+       if (x1 >= 0 && x1 != 3)
+         {
+           x2 = a3[i] - a1[i];
+           if (x2 >= 0 && x2 != 4)
+             {
+               x3 = a4[i] + a5[i];
+               if (x3 >= 0 && x3 != 5)
+                 {
+                   a6[i] = x1 - x2;
+                   a7[i] = x3 + x2;
+                 }
+             }
+         }
+    }
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
index ade692a39ae460b4464072de7ee97ca60b9995d3..400ee01a5122c0c74b21a9b100f36b2951e45a46 100644 (file)
@@ -1974,6 +1974,20 @@ insert_gimplified_predicates (loop_p loop, bool any_mask_load_store)
     }
 }
 
+/* Helper function for predicate_mem_writes. Returns index of existent
+   mask if it was created for given SIZE and -1 otherwise.  */
+
+static int
+mask_exists (int size, vec<int> vec)
+{
+  unsigned int ix;
+  int v;
+  FOR_EACH_VEC_ELT (vec, ix, v)
+    if (v == size)
+      return (int) ix;
+  return -1;
+}
+
 /* Predicate each write to memory in LOOP.
 
    This function transforms control flow constructs containing memory
@@ -2085,6 +2099,8 @@ static void
 predicate_mem_writes (loop_p loop)
 {
   unsigned int i, orig_loop_num_nodes = loop->num_nodes;
+  auto_vec<int, 1> vect_sizes;
+  auto_vec<tree, 1> vect_masks;
 
   for (i = 1; i < orig_loop_num_nodes; i++)
     {
@@ -2093,6 +2109,7 @@ predicate_mem_writes (loop_p loop)
       tree cond = bb_predicate (bb);
       bool swap;
       gimple stmt;
+      int index;
 
       if (is_true_predicate (cond))
        continue;
@@ -2104,6 +2121,9 @@ predicate_mem_writes (loop_p loop)
          cond = TREE_OPERAND (cond, 0);
        }
 
+      vect_sizes.truncate (0);
+      vect_masks.truncate (0);
+
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        if (!gimple_assign_single_p (stmt = gsi_stmt (gsi)))
          continue;
@@ -2114,21 +2134,31 @@ predicate_mem_writes (loop_p loop)
            tree ref, addr, ptr, masktype, mask_op0, mask_op1, mask;
            gimple new_stmt;
            int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs)));
-
-           masktype = build_nonstandard_integer_type (bitsize, 1);
-           mask_op0 = build_int_cst (masktype, swap ? 0 : -1);
-           mask_op1 = build_int_cst (masktype, swap ? -1 : 0);
            ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs;
            mark_addressable (ref);
            addr = force_gimple_operand_gsi (&gsi, build_fold_addr_expr (ref),
                                             true, NULL_TREE, true,
                                             GSI_SAME_STMT);
-           cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond),
-                                              is_gimple_condexpr, NULL_TREE,
-                                              true, GSI_SAME_STMT);
-           mask = fold_build_cond_expr (masktype, unshare_expr (cond),
-                                        mask_op0, mask_op1);
-           mask = ifc_temp_var (masktype, mask, &gsi);
+           if (!vect_sizes.is_empty ()
+               && (index = mask_exists (bitsize, vect_sizes)) != -1)
+             /* Use created mask.  */
+             mask = vect_masks[index];
+           else
+             {
+               masktype = build_nonstandard_integer_type (bitsize, 1);
+               mask_op0 = build_int_cst (masktype, swap ? 0 : -1);
+               mask_op1 = build_int_cst (masktype, swap ? -1 : 0);
+               cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond),
+                                                  is_gimple_condexpr,
+                                                  NULL_TREE,
+                                                  true, GSI_SAME_STMT);
+               mask = fold_build_cond_expr (masktype, unshare_expr (cond),
+                                            mask_op0, mask_op1);
+               mask = ifc_temp_var (masktype, mask, &gsi);
+               /* Save mask and its size for further use.  */
+               vect_sizes.safe_push (bitsize);
+               vect_masks.safe_push (mask);
+             }
            ptr = build_int_cst (reference_alias_ptr_type (ref), 0);
            /* Copy points-to info if possible.  */
            if (TREE_CODE (addr) == SSA_NAME && !SSA_NAME_PTR_INFO (addr))
@@ -2494,10 +2524,10 @@ ifcvt_walk_pattern_tree (tree var, vec<gimple> *defuse_list,
 }
 
 /* Returns true if STMT can be a root of bool pattern apllied
-   by vectorizer.  VAR contains SSA_NAME which starts pattern.  */
+   by vectorizer.  */
 
 static bool
-stmt_is_root_of_bool_pattern (gimple stmt, tree *var)
+stmt_is_root_of_bool_pattern (gimple stmt)
 {
   enum tree_code code;
   tree lhs, rhs;
@@ -2511,7 +2541,6 @@ stmt_is_root_of_bool_pattern (gimple stmt, tree *var)
        return false;
       if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE)
        return false;
-      *var = rhs;
       return true;
     }
   else if (code == COND_EXPR)
@@ -2519,7 +2548,6 @@ stmt_is_root_of_bool_pattern (gimple stmt, tree *var)
       rhs = gimple_assign_rhs1 (stmt);
       if (TREE_CODE (rhs) != SSA_NAME)
        return false;
-      *var = rhs;
       return true;
     }
   return false;
@@ -2538,23 +2566,49 @@ ifcvt_repair_bool_pattern (basic_block bb)
   gimple stmt;
   gimple_stmt_iterator gsi;
   vec<gimple> defuse_list = vNULL;
+  vec<gimple> pattern_roots = vNULL;
+  bool repeat = true;
+  int niter = 0;
+  unsigned int ix;
 
+  /* Collect all root pattern statements.  */
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     {
       stmt = gsi_stmt (gsi);
       if (gimple_code (stmt) != GIMPLE_ASSIGN)
        continue;
-      if (!stmt_is_root_of_bool_pattern (stmt, &rhs))
+      if (!stmt_is_root_of_bool_pattern (stmt))
        continue;
-      ifcvt_walk_pattern_tree (rhs, &defuse_list, stmt);
-      while (defuse_list.length () > 0)
+      pattern_roots.safe_push (stmt);
+    }
+
+  if (pattern_roots.is_empty ())
+    return;
+
+  /* Split all statements with multiple uses iteratively since splitting
+     may create new multiple uses.  */
+  while (repeat)
+    {
+      repeat = false;
+      niter++;
+      FOR_EACH_VEC_ELT (pattern_roots, ix, stmt)
        {
-         gimple def_stmt, use_stmt;
-         use_stmt = defuse_list.pop ();
-         def_stmt = defuse_list.pop ();
-         ifcvt_split_def_stmt (def_stmt, use_stmt);
+         rhs = gimple_assign_rhs1 (stmt);
+         ifcvt_walk_pattern_tree (rhs, &defuse_list, stmt);
+         while (defuse_list.length () > 0)
+           {
+             repeat = true;
+             gimple def_stmt, use_stmt;
+             use_stmt = defuse_list.pop ();
+             def_stmt = defuse_list.pop ();
+             ifcvt_split_def_stmt (def_stmt, use_stmt);
+           }
+
        }
     }
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "Repair bool pattern takes %d iterations. \n",
+            niter);
 }
 
 /* Delete redundant statements produced by predication which prevents