public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, 2/2] Extended if-conversion for loops marked with pragma omp simd.
@ 2014-10-13 10:01 Yuri Rumyantsev
  0 siblings, 0 replies; only message in thread
From: Yuri Rumyantsev @ 2014-10-13 10:01 UTC (permalink / raw)
  To: gcc-patches, Richard Biener, Igor Zamyatin

[-- Attachment #1: Type: text/plain, Size: 2240 bytes --]

Richard,

Here is second part of patch which includes
1. One particular phi node recognition  - if phi function has more
than 2 arguments but it has only two really different arguments and
one argument has the only occurrence. This is important for
conditional scalar reduction conversion, e.g. for such test-case;
     if (a[i] != 0 && b[i] != 0)  n++;
2. New sub-pass which repairs bool pattern candidates with multiple
uses - such situation occurres if the same predicate (not simple
compare) is used for phi node conversion and load/store mask. If for
some var participating in tree traversal its def stmt has multiple
uses we create copy of this definition with unique left hand side and
change one use of original vat to newly created one. We repeat this
process until all multiple uses will be deleted.
3. Another sub-pass which  delete redundant predicate computations
which are dead locally, i.e. local dead code elimination. Note that
such dead code can prevent loop vectorization.

Changelog:

2014-10-13  Yuri Rumyantsev  <ysrumyan@gmail.com>

* tree-if-conv.c (cgraph.h): Add include file to issue error message.
(phi_has_two_different_args): New function.
(is_cond_scalar_reduction): Add argument EXTENDED to choose access
to phi arguments. Invoke phi_has_two_different_args to get phi
arguments iff EXTENDED is true. Change check stmt-block is predecessor
of phi-block since phi may haave more than two arguments.
(convert_scalar_cond_reduction): Add argument BEFORE to insert
statement before/after gsi point.
(predicate_scalar_phi): Add argument false to call of
is_cond_scalar_reduction. Add argument true to call of
convert_scalar_cond_reduction.
(predicate_arbitrary_scalar_phi): Change result of function to tree
representing rhs of new phi replacement stmt.
(predicate_extended_scalar_phi): New function.
(predicate_all_scalar_phis): Invoke predicate_extended_scalar_phi
instead of predicate_arbitrary_scalar_phi.
(ifcvt_split_def_stmt): New function.
(ifcvt_walk_pattern_tree): New function.
(stmt_is_root_of_bool_pattern): New function.
(ifcvt_repair_bool_pattern): New function.
(ifcvt_local_dce): New function.
(tree_if_conversion): Invoke ifcvt_local_dce and
ifcvt_repair_bool_pattern under FLAG_FORCE_VECTORIZE.

[-- Attachment #2: patch.part-2 --]
[-- Type: application/octet-stream, Size: 18791 bytes --]

diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index f213506..019c439 100755
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -1497,6 +1497,66 @@ find_phi_replacement_condition (basic_block bb, tree *cond,
   return first_edge->src;
 }
 
+/* Returns true if phi arguments are equal except for one; argument values and
+   index of exclusive argument are saved if needed.  */
+
+static bool
+phi_has_two_different_args (gimple phi, tree *arg_0, tree *arg_1,
+			    unsigned int *index)
+{
+  unsigned int i, ind0 = 0, ind1;
+  tree arg0, arg1 = NULL_TREE;
+  bool seen_same = false;
+
+  arg0 = gimple_phi_arg_def (phi, 0);
+  for (i = 1; i < gimple_phi_num_args (phi); i++)
+    {
+      tree tmp;
+      tmp = gimple_phi_arg_def (phi, i);
+      if (arg0 == NULL_TREE
+	  && operand_equal_p (tmp, arg1, 0) == 0)
+	{
+	  arg0 = tmp;
+	  ind0 = i;
+	}
+      else if (seen_same && operand_equal_p (tmp, arg1, 0) != 0)
+	continue;
+      else if (operand_equal_p (tmp, arg0, 0) == 0)
+	{
+	  if (arg1 == NULL_TREE)
+	    {
+	      arg1 = tmp;
+	      ind1 = i;
+	    }
+	  else if (operand_equal_p (tmp, arg1, 0) == 0)
+	    return false;
+	  else
+	    seen_same = true;
+	}
+      else if (!seen_same)
+	{
+	  /* Swap arguments.  */
+	  seen_same = true;
+	  arg0 = arg1;
+	  arg1 = tmp;
+	  ind0 = ind1;
+	}
+      else
+	return false;
+    }
+  if (arg0 == NULL_TREE)
+    return false;
+
+  if (arg_0)
+    *arg_0 = arg0;
+  if (arg_1)
+    *arg_1 = arg1;
+  if (index)
+    *index = ind0;
+
+  return true;
+}
+
 /* Returns true if def-stmt for phi argument ARG is simple increment/decrement
    which is in predicated basic block.
    In fact, the following PHI pattern is searching:
@@ -1507,11 +1567,12 @@ find_phi_replacement_condition (basic_block bb, tree *cond,
 	  reduc_3 = ...
 	reduc_2 = PHI <reduc_1, reduc_3>
 
-   REDUC, OP0 and OP1 contain reduction stmt and its operands.  */
+   REDUC, OP0 and OP1 contain reduction stmt and its operands.
+   EXTENDED is used to get phi arguments through different methods.  */
 
 static bool
 is_cond_scalar_reduction (gimple phi, gimple *reduc,
-			  tree *op0, tree *op1)
+			  tree *op0, tree *op1, bool extended)
 {
   tree lhs, r_op1, r_op2;
   tree arg_0, arg_1;
@@ -1523,9 +1584,18 @@ is_cond_scalar_reduction (gimple phi, gimple *reduc,
   edge latch_e = loop_latch_edge (loop);
   imm_use_iterator imm_iter;
   use_operand_p use_p;
+  edge e;
+  edge_iterator ei;
+  bool result = false;
 
-  arg_0 = PHI_ARG_DEF (phi, 0);
-  arg_1 = PHI_ARG_DEF (phi, 1);
+  if (extended)
+    /* Phi may have more than 2 arguments, but only two are different.  */
+    phi_has_two_different_args (phi, &arg_0, &arg_1, NULL);
+  else
+    {
+      arg_0 = PHI_ARG_DEF (phi, 0);
+      arg_1 = PHI_ARG_DEF (phi, 1);
+    }
   if (TREE_CODE (arg_0) != SSA_NAME || TREE_CODE (arg_1) != SSA_NAME)
     return false;
 
@@ -1560,8 +1630,13 @@ is_cond_scalar_reduction (gimple phi, gimple *reduc,
     return false;
 
   /* Check that stmt-block is predecessor of phi-block.  */
-  if (EDGE_PRED (bb, 0)->src != gimple_bb (stmt)
-      && EDGE_PRED (bb, 1)->src != gimple_bb (stmt))
+  FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs)
+    if (e->dest == bb)
+      {
+	result = true;
+	break;
+      }
+  if (!result)
     return false;
 
   if (!has_single_use (lhs))
@@ -1617,11 +1692,13 @@ is_cond_scalar_reduction (gimple phi, gimple *reduc,
     res_2 = res_13 + _ifc__1;
   Argument SWAP tells that arguments of conditional expression should be
   swapped.
+  Argument BEFORE is used to insert new statement before/after.
   Returns rhs of resulting PHI assignment.  */
 
 static tree
 convert_scalar_cond_reduction (gimple reduc, gimple_stmt_iterator *gsi,
-			       tree cond, tree op0, tree op1, bool swap)
+			       tree cond, tree op0, tree op1, bool swap,
+			       bool before)
 {
   gimple_stmt_iterator stmt_it;
   gimple new_assign;
@@ -1636,7 +1713,6 @@ convert_scalar_cond_reduction (gimple reduc, gimple_stmt_iterator *gsi,
       fprintf (dump_file, "Found cond scalar reduction.\n");
       print_gimple_stmt (dump_file, reduc, 0, TDF_SLIM);
     }
-
   /* Build cond expression using COND and constant operand
      of reduction rhs.  */
   c = fold_build_cond_expr (TREE_TYPE (rhs1),
@@ -1646,7 +1722,10 @@ convert_scalar_cond_reduction (gimple reduc, gimple_stmt_iterator *gsi,
 
   /* Create assignment stmt and insert it at GSI.  */
   new_assign = gimple_build_assign (tmp, c);
-  gsi_insert_before (gsi, new_assign, GSI_SAME_STMT);
+  if (before)
+    gsi_insert_before (gsi, new_assign, GSI_SAME_STMT);
+  else
+    gsi_insert_after (gsi, new_assign, GSI_NEW_STMT);
   /* Build rhs for unconditional increment/decrement.  */
   rhs = fold_build2 (gimple_assign_rhs_code (reduc),
 		     TREE_TYPE (rhs1), op0, tmp);
@@ -1714,10 +1793,11 @@ predicate_scalar_phi (gimple phi, tree cond,
 	  arg_0 = gimple_phi_arg_def (phi, 0);
 	  arg_1 = gimple_phi_arg_def (phi, 1);
 	}
-      if (is_cond_scalar_reduction (phi, &reduc, &op0, &op1))
+      if (is_cond_scalar_reduction (phi, &reduc, &op0, &op1, false))
 	/* Convert reduction stmt into vectorizable form.  */
 	rhs = convert_scalar_cond_reduction (reduc, gsi, cond, op0, op1,
-					     true_bb != gimple_bb (reduc));
+					     true_bb != gimple_bb (reduc),
+					     true);
       else
 	/* Build new RHS using selected condition and arguments.  */
 	rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond),
@@ -1788,9 +1868,12 @@ get_predicate_for_edge (edge e)
 
     where <PRD_3> is predicate of <bb_3>.
 
-    All created intermediate statements are inserted at GSI point.  */
+    All created intermediate statements are inserted at GSI point
+    using value of argumnet BEFORE.
+    Returns cond expression correspondent to rhs of new phi
+    replacement stmt.  */
 
-static void
+static tree
 predicate_arbitrary_scalar_phi (gimple phi, gimple_stmt_iterator *gsi,
 				bool before)
 {
@@ -1801,15 +1884,9 @@ predicate_arbitrary_scalar_phi (gimple phi, gimple_stmt_iterator *gsi,
   tree curr;
   gimple stmt;
   tree lhs;
-  tree rhs;
-  tree res;
   tree cond;
   bool swap = false;
 
-  res = gimple_phi_result (phi);
-  if (virtual_operand_p (res))
-    return;
-
   for (i = num - 2; i > 0; i--)
     {
       curr = gimple_phi_arg_def (phi, i);
@@ -1864,21 +1941,73 @@ predicate_arbitrary_scalar_phi (gimple phi, gimple_stmt_iterator *gsi,
     cond = force_gimple_operand_gsi_1 (gsi, unshare_expr (cond),
 				       is_gimple_condexpr, NULL_TREE, false,
 				       GSI_CONTINUE_LINKING);
-  rhs = fold_build_cond_expr (type,
-			      unshare_expr (cond),
-			      swap? last : curr,
-			      swap? curr : last);
-  stmt = gimple_build_assign (res, rhs);
+
+  return fold_build_cond_expr (type,
+			       unshare_expr (cond),
+			       swap? last : curr,
+			       swap? curr : last);
+}
+
+/* Replace scalar phi node with more than 2 arguments. Distinguish
+   one important particular case if phi has only two different
+   arguments and one of them has the only occurance.  */
+
+static void
+predicate_extended_scalar_phi (gimple phi, gimple_stmt_iterator *gsi,
+			       bool before)
+{
+  gimple new_stmt, reduc;
+  tree rhs, res, arg0, arg1, op0, op1;
+  tree cond;
+  unsigned int index0;
+  edge e;
+  bool swap = false;
+
+  res = gimple_phi_result (phi);
+  if (virtual_operand_p (res))
+    return;
+
+  if (!phi_has_two_different_args (phi, &arg0, &arg1, &index0))
+    rhs = predicate_arbitrary_scalar_phi (phi, gsi, before);
+  else
+    {
+      e = gimple_phi_arg_edge (phi, index0);
+      cond = get_predicate_for_edge (e);
+      if (TREE_CODE (cond) == TRUTH_NOT_EXPR)
+	{
+	  swap = true;
+	  cond = TREE_OPERAND (cond, 0);
+	}
+      /* Gimplify the condition to a valid cond-expr conditonal operand.  */
+      if (before)
+	cond = force_gimple_operand_gsi_1 (gsi, unshare_expr (cond),
+					   is_gimple_condexpr, NULL_TREE,
+					   true, GSI_SAME_STMT);
+      else
+	cond = force_gimple_operand_gsi_1 (gsi, unshare_expr (cond),
+					   is_gimple_condexpr, NULL_TREE,
+					   false, GSI_CONTINUE_LINKING);
+
+      if (!(is_cond_scalar_reduction (phi, &reduc, &op0, &op1, true)))
+	rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond),
+				    swap? arg1 : arg0,
+				    swap? arg0 : arg1);
+      else
+	/* Convert reduction stmt into vectorizable form.  */
+	rhs = convert_scalar_cond_reduction (reduc, gsi, cond, op0, op1,
+					     swap, before);
+    }
+  new_stmt = gimple_build_assign (res, rhs);
   if (before)
-    gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
+    gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
   else
-    gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
-  update_stmt (stmt);
+    gsi_insert_after (gsi, new_stmt, GSI_NEW_STMT);
+  update_stmt (new_stmt);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf (dump_file, "new phi replacement stmt\n");
-      print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+      fprintf (dump_file, "new ext. phi replacement stmt\n");
+      print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM);
     }
 }
 
@@ -2006,7 +2135,7 @@ predicate_all_scalar_phis (struct loop *loop)
 	  if (true_bb)
 	    predicate_scalar_phi (phi, cond, true_bb, &gsi);
 	  else
-	    predicate_arbitrary_scalar_phi (phi, &gsi, before);
+	    predicate_extended_scalar_phi (phi, &gsi, before);
 	  release_phi_node (phi);
 	  gsi_next (&phi_gsi);
 	}
@@ -2450,6 +2579,316 @@ version_loop_for_if_conversion (struct loop *loop)
   return true;
 }
 
+/* Assumes that lhs of DEF_STMT have multiple uses.
+   Delete one use by (1) creation of copy DEF_STMT with
+   unique lhs; (2) change original use of lhs in one
+   use statement with newly created lhs.  */
+
+static void
+ifcvt_split_def_stmt (gimple def_stmt)
+{
+  tree var;
+  tree lhs;
+  tree opnd;
+  gimple copy_stmt;
+  gimple_stmt_iterator gsi;
+  gimple use_stmt = NULL;
+  use_operand_p use_p;
+  imm_use_iterator imm_iter;
+  unsigned int i;
+
+  var = gimple_assign_lhs (def_stmt);
+  copy_stmt = gimple_copy (def_stmt);
+  lhs = make_temp_ssa_name (TREE_TYPE (var), NULL, "_ifc_");
+  gimple_assign_set_lhs (copy_stmt, lhs);
+  SSA_NAME_DEF_STMT (lhs) = copy_stmt;
+  /* Insert copy of DEF_STMT.  */
+  gsi = gsi_for_stmt (def_stmt);
+  gsi_insert_after (&gsi, copy_stmt, GSI_SAME_STMT);
+  /* Change one use of var to lhs.  */
+  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
+    {
+      use_stmt = USE_STMT (use_p);
+      break;
+    }
+  gcc_assert (gimple_code (use_stmt) == GIMPLE_ASSIGN);
+  copy_stmt = gimple_copy (use_stmt);
+  for (i = 0; i < gimple_num_ops (use_stmt); i++)
+    {
+      opnd = gimple_op (copy_stmt, i);
+      if (TREE_CODE (opnd) == SSA_NAME)
+	{
+	  if (opnd == var)
+	    {
+	      gimple_set_op (copy_stmt, i, lhs);
+	      break;
+	    }
+	}
+      else if (CONSTANT_CLASS_P (opnd))
+	;
+      else
+	{
+	  if (TREE_CODE (TREE_OPERAND (opnd, 0)) == SSA_NAME
+	      && TREE_OPERAND (opnd, 0) == var)
+	    TREE_OPERAND (opnd, 0) = lhs;
+	  else if (TREE_CODE_LENGTH (TREE_CODE (opnd)) > 1
+		   && TREE_CODE (TREE_OPERAND (opnd, 1)) == SSA_NAME
+		   && TREE_OPERAND (opnd, 1) == var)
+	    TREE_OPERAND (opnd, 1) = lhs;
+	}
+    }
+  SSA_NAME_DEF_STMT (gimple_assign_lhs(copy_stmt)) = copy_stmt;
+  gsi = gsi_for_stmt (use_stmt);
+  gsi_insert_before (&gsi, copy_stmt, GSI_SAME_STMT);
+  /* Remove old use.  */
+  gsi_remove (&gsi, true);
+}
+
+/* Traverse tree recursively starting from var and check if given tree
+   can represent bool pattern.
+   Returns true if tree can be considered as bool pattern candidate.
+   Retry is true if traversal restart is required.  */
+
+static bool
+ifcvt_walk_pattern_tree (tree var, bool *retry)
+{
+  tree rhs1;
+  enum tree_code code;
+  gimple def_stmt;
+
+  def_stmt = SSA_NAME_DEF_STMT (var);
+  if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
+    return false;
+  if (!has_single_use (var))
+    {
+      use_operand_p use_p;
+      imm_use_iterator imm_iter;
+      gimple use_stmt;
+      /* If theere are uses outside of loop do not consider
+	 such tree as candidate for bool pattern.  */
+      FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
+	{
+	  use_stmt = USE_STMT (use_p);
+	  if (gimple_bb (use_stmt) != gimple_bb (def_stmt))
+	    return false;
+	}
+      /* Need to repair tree by deletion multiple uses.  */
+      *retry = true;
+      ifcvt_split_def_stmt (def_stmt);
+      return true;
+    }
+  rhs1 = gimple_assign_rhs1 (def_stmt);
+  code = gimple_assign_rhs_code (def_stmt);
+  switch (code)
+    {
+    case SSA_NAME:
+      return ifcvt_walk_pattern_tree (rhs1, retry);
+    CASE_CONVERT:
+      if ((TYPE_PRECISION (TREE_TYPE (rhs1)) != 1
+	   || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
+	  && TREE_CODE (TREE_TYPE (rhs1)) != BOOLEAN_TYPE)
+	return false;
+      return ifcvt_walk_pattern_tree (rhs1, retry);
+    case BIT_NOT_EXPR:
+      return ifcvt_walk_pattern_tree (rhs1, retry);
+    case BIT_AND_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+      if (!ifcvt_walk_pattern_tree (rhs1, retry))
+	return false;
+      return ifcvt_walk_pattern_tree (gimple_assign_rhs2 (def_stmt), retry);
+    default:
+      if (TREE_CODE_CLASS (code) == tcc_comparison)
+	return true;
+    }
+  return false;
+}
+
+/* Returns true if STMT can be a root of bool pattern apllied
+   by vectorizer. VAR contains SSA_NAME which starts pattern.  */
+
+static bool
+stmt_is_root_of_bool_pattern (gimple stmt, tree *var)
+{
+  enum tree_code code;
+  tree lhs, rhs;
+
+  code = gimple_assign_rhs_code (stmt);
+  if (CONVERT_EXPR_CODE_P (code))
+    {
+      lhs = gimple_assign_lhs (stmt);
+      rhs = gimple_assign_rhs1 (stmt);
+      if (TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE)
+	return false;
+      if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE)
+	return false;
+      *var = rhs;
+      return true;
+    }
+  else if (code == COND_EXPR)
+    {
+      rhs = gimple_assign_rhs1 (stmt);
+      if (TREE_CODE (rhs) != SSA_NAME)
+	return false;
+      *var = rhs;
+      return true;
+    }
+  return false;
+}
+
+/*  Traverse all statements in BB which correspondentt to loop header to
+    find out all statements which can start bool pattern applied by
+    vectorizer and convert multiple uses in it to conform pattern
+    restrictions. Such case can occur if the same predicate is used both
+    for phi node conversion and load/store mask.  */
+
+static void
+ifcvt_repair_bool_pattern (basic_block bb)
+{
+  gimple stmt;
+  tree rhs;
+  gimple_stmt_iterator gsi;
+  bool retry;
+
+  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))
+	continue;
+      while (true)
+	{
+	  retry = false;
+	  if (!ifcvt_walk_pattern_tree (rhs, &retry))
+	    return;
+	  if (!retry)
+	    break;
+	}
+    }
+}
+
+/* Delete redundant statements produced by predication which prevents
+   loop vectorization.  */
+
+static void
+ifcvt_local_dce (basic_block bb)
+{
+  gimple stmt;
+  gimple stmt1;
+  gimple phi;
+  gimple_stmt_iterator gsi;
+  vec<gimple> worklist;
+  enum gimple_code code;
+  unsigned int i;
+  use_operand_p use_p;
+  imm_use_iterator imm_iter;
+
+
+  worklist.create (64);
+  /* Consider all phi as live statements.  */
+  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      phi = gsi_stmt (gsi);
+      gimple_set_plf (phi, GF_PLF_2, true);
+      worklist.safe_push (phi);
+    }
+  /* Consider load/store statemnts, CALL and COND as live.  */
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      stmt = gsi_stmt (gsi);
+      if (gimple_store_p (stmt)
+	  || gimple_assign_load_p (stmt))
+	{
+	  gimple_set_plf (stmt, GF_PLF_2, true);
+	  worklist.safe_push (stmt);
+	  continue;
+	}
+      code = gimple_code (stmt);
+      if (code == GIMPLE_COND || code == GIMPLE_CALL)
+	{
+	  gimple_set_plf (stmt, GF_PLF_2, true);
+	  worklist.safe_push (stmt);
+	  continue;
+	}
+      gimple_set_plf (stmt, GF_PLF_2, false);
+
+      if (code == GIMPLE_ASSIGN)
+	{
+	  tree lhs = gimple_assign_lhs (stmt);
+	  /* Consider gimples with uses outside of loop as live.  */
+	  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
+	    {
+	      stmt1 = USE_STMT (use_p);
+	      if (gimple_bb (stmt1) != bb)
+		{
+		  gimple_set_plf (stmt, GF_PLF_2, true);
+		  worklist.safe_push (stmt);
+		  break;
+		}
+	    }
+	}
+    }
+  /* Propagate liveness through arguments of live stmt.  */
+  while (worklist.length () > 0)
+    {
+      stmt = worklist.pop ();
+      code = gimple_code (stmt);
+      if (gimple_code (stmt) == GIMPLE_PHI)
+	{
+	  for (i = 0; i < gimple_phi_num_args (stmt); i++)
+	    {
+	      tree arg = PHI_ARG_DEF (stmt, i);
+	      if (TREE_CODE (arg) == SSA_NAME)
+		{
+		  stmt1 = SSA_NAME_DEF_STMT (arg);
+		  if (gimple_bb (stmt1) != bb
+		      || gimple_plf (stmt1, GF_PLF_2))
+		    continue;
+		  gimple_set_plf (stmt1, GF_PLF_2, true);
+		  worklist.safe_push (stmt1);
+		}
+	    }
+	}
+      else
+	{
+	  tree use;
+	  ssa_op_iter iter;
+	  FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
+	    {
+	      stmt1 = SSA_NAME_DEF_STMT (use);
+	      if (gimple_bb (stmt1) != bb
+		  || gimple_plf (stmt1, GF_PLF_2))
+		continue;
+	      gimple_set_plf (stmt1, GF_PLF_2, true);
+	      worklist.safe_push (stmt1);
+	   }
+	}
+    }
+  /* Delete dead statements.  */
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple_stmt_iterator stmt_it;
+      /* tree lhs; */
+
+      stmt = gsi_stmt (gsi);
+      if (gimple_plf (stmt, GF_PLF_2))
+	{
+	  gimple_set_plf (stmt, GF_PLF_2, false);
+	  continue;
+	}
+      gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "Delete dead stmt:\n");
+	  print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+	}
+      stmt_it = gsi_for_stmt (stmt);
+      gsi_remove (&stmt_it, true);
+      release_defs (stmt);
+    }
+  worklist.release();
+}
 
 /* If-convert LOOP when it is legal.  For the moment this pass has no
    profitability analysis.  Returns non-zero todo flags when something
@@ -2490,6 +2929,15 @@ tree_if_conversion (struct loop *loop)
      on-the-fly.  */
   combine_blocks (loop, any_mask_load_store);
 
+  /* Delete dead statments produced by predication which can prevent
+     loop vectorization. Repair tree correspondent to bool pattern
+     to delete multiple uses of preidcates.  */
+  if (flag_force_vectorize)
+    {
+      ifcvt_local_dce (loop->header);
+      ifcvt_repair_bool_pattern (loop->header);
+    }
+
   todo |= TODO_cleanup_cfg;
   if (flag_tree_loop_if_convert_stores || any_mask_load_store)
     {

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-10-13 10:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-13 10:01 [PATCH, 2/2] Extended if-conversion for loops marked with pragma omp simd Yuri Rumyantsev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).