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
index 0000000..a9a88e1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c
@@ -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" } } */
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 8b113fe..f28b2d2 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -1954,6 +1954,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
@@ -2065,6 +2079,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++)
     {
@@ -2073,6 +2089,7 @@ predicate_mem_writes (loop_p loop)
       tree cond = bb_predicate (bb);
       bool swap;
       gimple stmt;
+      int index;
 
       if (is_true_predicate (cond))
 	continue;
@@ -2084,6 +2101,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;
@@ -2094,21 +2114,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))
@@ -2474,10 +2504,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;
@@ -2491,7 +2521,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)
@@ -2499,7 +2528,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;
@@ -2518,23 +2546,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
