Patchwork Fix PR43430: vectorize conditionals with multiple types

login
register
mail settings
Submitter Michael Matz
Date Sept. 7, 2010, 1:10 p.m.
Message ID <Pine.LNX.4.64.1009071507470.29722@wotan.suse.de>
Download mbox | patch
Permalink /patch/64010/
State New
Headers show

Comments

Michael Matz - Sept. 7, 2010, 1:10 p.m.
Hi,

for this testcase we need to emit multiple vectorized conditional 
statement per original statement (ncopies > 1).  This patch implements the 
support for that in case the conditional isn't part of a reduction (I'm 
didn't 100% follow the code under which conditions reduc_index is != 0 and 
what reduc_def then is, exactly).

Regstrapped on x86_64-linux, no regressions.  Okay?


Ciao,
Michael.
Richard Guenther - Sept. 7, 2010, 1:40 p.m.
On Tue, Sep 7, 2010 at 3:10 PM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> for this testcase we need to emit multiple vectorized conditional
> statement per original statement (ncopies > 1).  This patch implements the
> support for that in case the conditional isn't part of a reduction (I'm
> didn't 100% follow the code under which conditions reduc_index is != 0 and
> what reduc_def then is, exactly).
>
> Regstrapped on x86_64-linux, no regressions.  Okay?

Ok.

Thanks,
Richard.

>
> Ciao,
> Michael.
> --
>        PR tree-optimization/43430
>        * tree-vect-stmts.c (vectorizable_condition): Support multiple
>        copies for conditional statements if it's not part of a reduction.
>
> testsuite/
>        PR tree-optimization/43430
>        * gcc.dg/vect/pr43430-2.c: New test.
>
> Index: tree-vect-stmts.c
> ===================================================================
> --- tree-vect-stmts.c   (revision 163773)
> +++ tree-vect-stmts.c   (working copy)
> @@ -4011,16 +4011,18 @@ vectorizable_condition (gimple stmt, gim
>   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
>   enum machine_mode vec_mode;
>   tree def;
> -  enum vect_def_type dt;
> +  enum vect_def_type dt, dts[4];
>   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
>   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
>   enum tree_code code;
> +  stmt_vec_info prev_stmt_info = NULL;
> +  int j;
>
>   /* FORNOW: unsupported in basic block SLP.  */
>   gcc_assert (loop_vinfo);
>
>   gcc_assert (ncopies >= 1);
> -  if (ncopies > 1)
> +  if (reduc_index && ncopies > 1)
>     return false; /* FORNOW */
>
>   if (!STMT_VINFO_RELEVANT_P (stmt_info))
> @@ -4107,29 +4109,68 @@ vectorizable_condition (gimple stmt, gim
>   vec_dest = vect_create_destination_var (scalar_dest, vectype);
>
>   /* Handle cond expr.  */
> -  vec_cond_lhs =
> -    vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt, NULL);
> -  vec_cond_rhs =
> -    vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), stmt, NULL);
> -  if (reduc_index == 1)
> -    vec_then_clause = reduc_def;
> -  else
> -    vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt, NULL);
> -  if (reduc_index == 2)
> -    vec_else_clause = reduc_def;
> -  else
> -    vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt, NULL);
> -
> -  /* Arguments are ready. Create the new vector stmt.  */
> -  vec_compare = build2 (TREE_CODE (cond_expr), vectype,
> -                       vec_cond_lhs, vec_cond_rhs);
> -  vec_cond_expr = build3 (VEC_COND_EXPR, vectype,
> -                         vec_compare, vec_then_clause, vec_else_clause);
> -
> -  *vec_stmt = gimple_build_assign (vec_dest, vec_cond_expr);
> -  new_temp = make_ssa_name (vec_dest, *vec_stmt);
> -  gimple_assign_set_lhs (*vec_stmt, new_temp);
> -  vect_finish_stmt_generation (stmt, *vec_stmt, gsi);
> +  for (j = 0; j < ncopies; j++)
> +    {
> +      gimple new_stmt;
> +      if (j == 0)
> +       {
> +         gimple gtemp;
> +         vec_cond_lhs =
> +             vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
> +                                           stmt, NULL);
> +         vect_is_simple_use (TREE_OPERAND (cond_expr, 0), loop_vinfo,
> +                             NULL, &gtemp, &def, &dts[0]);
> +         vec_cond_rhs =
> +             vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
> +                                           stmt, NULL);
> +         vect_is_simple_use (TREE_OPERAND (cond_expr, 1), loop_vinfo,
> +                             NULL, &gtemp, &def, &dts[1]);
> +         if (reduc_index == 1)
> +           vec_then_clause = reduc_def;
> +         else
> +           {
> +             vec_then_clause = vect_get_vec_def_for_operand (then_clause,
> +                                                             stmt, NULL);
> +             vect_is_simple_use (then_clause, loop_vinfo,
> +                                 NULL, &gtemp, &def, &dts[2]);
> +           }
> +         if (reduc_index == 2)
> +           vec_else_clause = reduc_def;
> +         else
> +           {
> +             vec_else_clause = vect_get_vec_def_for_operand (else_clause,
> +                                                             stmt, NULL);
> +             vect_is_simple_use (else_clause, loop_vinfo,
> +                                 NULL, &gtemp, &def, &dts[3]);
> +           }
> +       }
> +      else
> +       {
> +         vec_cond_lhs = vect_get_vec_def_for_stmt_copy (dts[0], vec_cond_lhs);
> +         vec_cond_rhs = vect_get_vec_def_for_stmt_copy (dts[1], vec_cond_rhs);
> +         vec_then_clause = vect_get_vec_def_for_stmt_copy (dts[2],
> +                                                           vec_then_clause);
> +         vec_else_clause = vect_get_vec_def_for_stmt_copy (dts[3],
> +                                                           vec_else_clause);
> +       }
> +
> +      /* Arguments are ready. Create the new vector stmt.  */
> +      vec_compare = build2 (TREE_CODE (cond_expr), vectype,
> +                           vec_cond_lhs, vec_cond_rhs);
> +      vec_cond_expr = build3 (VEC_COND_EXPR, vectype,
> +                             vec_compare, vec_then_clause, vec_else_clause);
> +
> +      new_stmt = gimple_build_assign (vec_dest, vec_cond_expr);
> +      new_temp = make_ssa_name (vec_dest, new_stmt);
> +      gimple_assign_set_lhs (new_stmt, new_temp);
> +      vect_finish_stmt_generation (stmt, new_stmt, gsi);
> +      if (j == 0)
> +        STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
> +      else
> +        STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
> +
> +      prev_stmt_info = vinfo_for_stmt (new_stmt);
> +    }
>
>   return true;
>  }
> Index: testsuite/gcc.dg/vect/pr43430-2.c
> ===================================================================
> --- testsuite/gcc.dg/vect/pr43430-2.c   (revision 0)
> +++ testsuite/gcc.dg/vect/pr43430-2.c   (revision 0)
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target vect_int } */
> +/* { dg-options "-O3 -fno-vect-cost-model -fdump-tree-vect-details" } */
> +typedef unsigned char uint8_t;
> +vsad16_c (void *c, uint8_t * s1, uint8_t * s2, int stride, int h)
> +{
> +  int score = 0;
> +  int x, y;
> +  for (x = 0; x < 16; x++)
> +    score += ((s1[x] - s1[x + stride] + s2[x + stride]) >= 0 ?
> +              s1[x] + s2[x + stride] :
> +              s2[x + stride]);
> +  return score;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_condition } } } */
> +/* { dg-final { cleanup-tree-dump "vect" } } */
>

Patch

Index: tree-vect-stmts.c
===================================================================
--- tree-vect-stmts.c	(revision 163773)
+++ tree-vect-stmts.c	(working copy)
@@ -4011,16 +4011,18 @@  vectorizable_condition (gimple stmt, gim
   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
   enum machine_mode vec_mode;
   tree def;
-  enum vect_def_type dt;
+  enum vect_def_type dt, dts[4];
   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
   enum tree_code code;
+  stmt_vec_info prev_stmt_info = NULL;
+  int j;
 
   /* FORNOW: unsupported in basic block SLP.  */
   gcc_assert (loop_vinfo);
 
   gcc_assert (ncopies >= 1);
-  if (ncopies > 1)
+  if (reduc_index && ncopies > 1)
     return false; /* FORNOW */
 
   if (!STMT_VINFO_RELEVANT_P (stmt_info))
@@ -4107,29 +4109,68 @@  vectorizable_condition (gimple stmt, gim
   vec_dest = vect_create_destination_var (scalar_dest, vectype);
 
   /* Handle cond expr.  */
-  vec_cond_lhs =
-    vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt, NULL);
-  vec_cond_rhs =
-    vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), stmt, NULL);
-  if (reduc_index == 1)
-    vec_then_clause = reduc_def;
-  else
-    vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt, NULL);
-  if (reduc_index == 2)
-    vec_else_clause = reduc_def;
-  else
-    vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt, NULL);
-
-  /* Arguments are ready. Create the new vector stmt.  */
-  vec_compare = build2 (TREE_CODE (cond_expr), vectype,
-			vec_cond_lhs, vec_cond_rhs);
-  vec_cond_expr = build3 (VEC_COND_EXPR, vectype,
-			  vec_compare, vec_then_clause, vec_else_clause);
-
-  *vec_stmt = gimple_build_assign (vec_dest, vec_cond_expr);
-  new_temp = make_ssa_name (vec_dest, *vec_stmt);
-  gimple_assign_set_lhs (*vec_stmt, new_temp);
-  vect_finish_stmt_generation (stmt, *vec_stmt, gsi);
+  for (j = 0; j < ncopies; j++)
+    {
+      gimple new_stmt;
+      if (j == 0)
+	{
+	  gimple gtemp;
+	  vec_cond_lhs =
+	      vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
+					    stmt, NULL);
+	  vect_is_simple_use (TREE_OPERAND (cond_expr, 0), loop_vinfo,
+			      NULL, &gtemp, &def, &dts[0]);
+	  vec_cond_rhs =
+	      vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
+					    stmt, NULL);
+	  vect_is_simple_use (TREE_OPERAND (cond_expr, 1), loop_vinfo,
+			      NULL, &gtemp, &def, &dts[1]);
+	  if (reduc_index == 1)
+	    vec_then_clause = reduc_def;
+	  else
+	    {
+	      vec_then_clause = vect_get_vec_def_for_operand (then_clause,
+							      stmt, NULL);
+	      vect_is_simple_use (then_clause, loop_vinfo,
+				  NULL, &gtemp, &def, &dts[2]);
+	    }
+	  if (reduc_index == 2)
+	    vec_else_clause = reduc_def;
+	  else
+	    {
+	      vec_else_clause = vect_get_vec_def_for_operand (else_clause,
+							      stmt, NULL);
+	      vect_is_simple_use (else_clause, loop_vinfo,
+				  NULL, &gtemp, &def, &dts[3]);
+	    }
+	}
+      else
+	{
+	  vec_cond_lhs = vect_get_vec_def_for_stmt_copy (dts[0], vec_cond_lhs);
+	  vec_cond_rhs = vect_get_vec_def_for_stmt_copy (dts[1], vec_cond_rhs);
+	  vec_then_clause = vect_get_vec_def_for_stmt_copy (dts[2],
+							    vec_then_clause);
+	  vec_else_clause = vect_get_vec_def_for_stmt_copy (dts[3],
+							    vec_else_clause);
+	}
+
+      /* Arguments are ready. Create the new vector stmt.  */
+      vec_compare = build2 (TREE_CODE (cond_expr), vectype,
+			    vec_cond_lhs, vec_cond_rhs);
+      vec_cond_expr = build3 (VEC_COND_EXPR, vectype,
+			      vec_compare, vec_then_clause, vec_else_clause);
+
+      new_stmt = gimple_build_assign (vec_dest, vec_cond_expr);
+      new_temp = make_ssa_name (vec_dest, new_stmt);
+      gimple_assign_set_lhs (new_stmt, new_temp);
+      vect_finish_stmt_generation (stmt, new_stmt, gsi);
+      if (j == 0)
+        STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+      else
+        STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+
+      prev_stmt_info = vinfo_for_stmt (new_stmt);
+    }
 
   return true;
 }
Index: testsuite/gcc.dg/vect/pr43430-2.c
===================================================================
--- testsuite/gcc.dg/vect/pr43430-2.c	(revision 0)
+++ testsuite/gcc.dg/vect/pr43430-2.c	(revision 0)
@@ -0,0 +1,17 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-options "-O3 -fno-vect-cost-model -fdump-tree-vect-details" } */
+typedef unsigned char uint8_t;
+vsad16_c (void *c, uint8_t * s1, uint8_t * s2, int stride, int h)
+{
+  int score = 0;
+  int x, y;
+  for (x = 0; x < 16; x++)
+    score += ((s1[x] - s1[x + stride] + s2[x + stride]) >= 0 ?
+              s1[x] + s2[x + stride] :
+              s2[x + stride]);
+  return score;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_condition } } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */