public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Changes for if-convert to recognize simple conditional reduction.
@ 2014-04-17 13:23 Yuri Rumyantsev
  2014-04-28 12:21 ` Richard Biener
  2014-04-28 20:05 ` Richard Henderson
  0 siblings, 2 replies; 10+ messages in thread
From: Yuri Rumyantsev @ 2014-04-17 13:23 UTC (permalink / raw)
  To: gcc-patches, Igor Zamyatin

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

Hi All,

We implemented enhancement for if-convert phase to recognize the
simplest conditional reduction and to transform it vectorizable form,
e.g. statement
    if (A[i] != 0) num+= 1; will be recognized.
A new test-case is also provided.

Bootstrapping and regression testing did not show any new failures.

Is it OK for trunk?

gcc/ChangeLog:
2014-04-17  Yuri Rumyantsev  <ysrumyan@gmail.com>

* tree-if-conv.c (is_cond_scalar_reduction): New function.
(convert_scalar_cond_reduction): Likewise.
(predicate_scalar_phi): Add recognition and transformation
of simple conditioanl reduction to be vectorizable.

gcc/testsuite/ChangeLog:
2014-04-17  Yuri Rumyantsev  <ysrumyan@gmail.com>

* gcc.dg/cond-reduc.c: New test.

[-- Attachment #2: if-conv-cond-reduc.patch --]
[-- Type: application/octet-stream, Size: 5709 bytes --]

diff --git a/gcc/testsuite/gcc.dg/vect/cond-reduc.c b/gcc/testsuite/gcc.dg/vect/cond-reduc.c
new file mode 100755
index 0000000..981f6b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/cond-reduc.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+#define N 512
+int a[N];
+int foo()
+{
+  int i, res = 0;
+  for (i=0; i<N; i++)
+  {
+    if (a[i] != 0)
+      res += 1;
+  }
+  return res;
+}
+
+/* { 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
old mode 100644
new mode 100755
index 7ff2132..c33c406
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -1386,6 +1386,125 @@ find_phi_replacement_condition (basic_block bb, tree *cond,
   return first_edge->src;
 }
 
+/* Returns true if def-stmt for phi argument ARG is simple increment/decrement
+   with constant which is in predicated basic block.
+   REDUC, OP0 and OP1 contain reduction stmt, its var and const
+   operands respectively.  */
+
+static bool
+is_cond_scalar_reduction (tree arg, gimple *reduc, tree *op0, tree *op1)
+{
+  tree lhs, r_op1, r_op2;
+  gimple stmt;
+  gimple use_stmt;
+  use_operand_p use;
+  basic_block bb;
+  enum tree_code reduction_op;
+
+  if (TREE_CODE (arg) != SSA_NAME)
+    return false;
+  stmt = SSA_NAME_DEF_STMT (arg);
+  if (gimple_code (stmt) != GIMPLE_ASSIGN)
+    return false;
+
+  /* Consider only conditional reduction.  */
+  bb = gimple_bb (stmt);
+  if (!bb_has_predicate (bb))
+    return false;
+  if (is_true_predicate (bb_predicate (bb)))
+    return false;
+
+  lhs = gimple_assign_lhs (stmt);
+  if (TREE_CODE (lhs) != SSA_NAME)
+    return false;
+  if (SSA_NAME_VAR (lhs) == NULL)
+    return false;
+  if (!single_imm_use (lhs, &use, &use_stmt))
+    return false;
+  if (gimple_code (use_stmt) != GIMPLE_PHI)
+    return false;
+
+  reduction_op = gimple_assign_rhs_code (stmt);
+  if (reduction_op != PLUS_EXPR && reduction_op != MINUS_EXPR)
+    return false;
+  r_op1 = gimple_assign_rhs1 (stmt);
+  r_op2 = gimple_assign_rhs2 (stmt);
+  if (reduction_op == PLUS_EXPR &&
+      TREE_CODE (r_op2) == SSA_NAME)
+    {
+      tree tmp = r_op2;
+      r_op2 = r_op1;
+      r_op1 = tmp;
+    }
+  if (gimple_code (SSA_NAME_DEF_STMT (r_op1)) != GIMPLE_PHI)
+    return false;
+  if (TREE_CODE (r_op2) != INTEGER_CST && TREE_CODE (r_op2) != REAL_CST)
+    return false;
+  /* Right operand is constant, check that left operand is equal to lhs.  */
+  if (SSA_NAME_VAR (lhs) !=  SSA_NAME_VAR (r_op1))
+    return false;
+  *op0 = r_op1; *op1 = r_op2;
+  *reduc = stmt;
+  return true;
+}
+
+/* Converts conditional scalar reduction into unconditional form, e.g.
+     bb_4
+       if (_5 != 0) goto bb_5 else goto bb_6
+     end_bb_4
+     bb_5
+       res_6 = res_13 + 1;
+     end_bb_5
+     bb_6
+       # res_2 = PHI <res_13(4), res_6(5)>
+     end_bb_6
+
+   will be converted into sequence
+    _ifc__1 = _5 != 0 ? 1 : 0;
+    res_2 = res_13 + _ifc__1;
+  Argument SWAP tells that arguments of conditional expression should be
+  swapped.
+  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)
+{
+  gimple_stmt_iterator stmt_it;
+  gimple new_assign;
+  tree rhs;
+  tree rhs1 = gimple_assign_rhs1 (reduc);
+  tree tmp = make_temp_ssa_name (TREE_TYPE (rhs1), NULL, "_ifc_");
+  tree c;
+  tree zero = build_zero_cst (TREE_TYPE (rhs1));
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "Found cond scalar reduction");
+      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),
+			    unshare_expr (cond),
+			    swap? zero: op1,
+			    swap? op1: zero);
+
+  /* Create assignment stmt and insert it at GSI.  */
+  new_assign = gimple_build_assign (tmp, c);
+  gsi_insert_before (gsi, new_assign, GSI_SAME_STMT);
+  update_stmt (new_assign);
+  /* Build rhs for unconditional increment/decrement.  */
+  rhs = build2 (gimple_assign_rhs_code (reduc), TREE_TYPE (rhs1), op0, tmp);
+
+  /* Delete original reduction stmt.  */
+  stmt_it = gsi_for_stmt (reduc);
+  gsi_remove (&stmt_it, true);
+  release_defs (reduc);
+  return rhs;
+}
+
 /* Replace a scalar PHI node with a COND_EXPR using COND as condition.
    This routine does not handle PHI nodes with more than two
    arguments.
@@ -1428,6 +1547,8 @@ predicate_scalar_phi (gimple phi, tree cond,
   else
     {
       tree arg_0, arg_1;
+      tree op0, op1;
+      gimple reduc;
       /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr.  */
       if (EDGE_PRED (bb, 1)->src == true_bb)
 	{
@@ -1439,10 +1560,15 @@ predicate_scalar_phi (gimple phi, tree cond,
 	  arg_0 = gimple_phi_arg_def (phi, 0);
 	  arg_1 = gimple_phi_arg_def (phi, 1);
 	}
-
-      /* Build new RHS using selected condition and arguments.  */
-      rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond),
-				  arg_0, arg_1);
+      if (!(is_cond_scalar_reduction (arg_0, &reduc, &op0, &op1)
+	    || is_cond_scalar_reduction (arg_1, &reduc, &op0, &op1)))
+	/* Build new RHS using selected condition and arguments.  */
+	rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond),
+				    arg_0, arg_1);
+      else
+	/* Convert reduction stmt into vectorizable form.  */
+	rhs = convert_scalar_cond_reduction (reduc, gsi, cond, op0, op1,
+					     true_bb != gimple_bb (reduc));
     }
 
   new_stmt = gimple_build_assign (res, rhs);

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-05-05  9:06 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-17 13:23 Changes for if-convert to recognize simple conditional reduction Yuri Rumyantsev
2014-04-28 12:21 ` Richard Biener
2014-04-29 14:36   ` Yuri Rumyantsev
2014-04-30 12:45     ` Richard Biener
2014-04-30 16:46       ` Yuri Rumyantsev
2014-04-30 17:42         ` H.J. Lu
2014-05-05  7:44         ` Richard Biener
2014-05-05  9:06           ` Yuri Rumyantsev
2014-04-28 20:05 ` Richard Henderson
2014-04-29  9:16   ` Richard Biener

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).