public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [vec-cmp, patch 4/6] Support vector mask invariants
@ 2015-10-08 15:12 Ilya Enkovich
  2015-10-13 13:54 ` Richard Biener
  0 siblings, 1 reply; 9+ messages in thread
From: Ilya Enkovich @ 2015-10-08 15:12 UTC (permalink / raw)
  To: gcc-patches

Hi,

This patch adds a special handling of boolean vector invariants.  We need additional code to determine type of generated invariant.  For VEC_COND_EXPR case we even provide this type directly because statement vectype doesn't allow us to compute it.  Separate code is used to generate and expand such vectors.

Thanks,
Ilya
--
gcc/

2015-10-08  Ilya Enkovich  <enkovich.gnu@gmail.com>

	* expr.c (const_vector_mask_from_tree): New.
	(const_vector_from_tree): Use const_vector_mask_from_tree
	for boolean vectors.
	* tree-vect-stmts.c (vect_init_vector): Support boolean vector
	invariants.
	(vect_get_vec_def_for_operand): Add VECTYPE arg.
	(vectorizable_condition): Directly provide vectype for invariants
	used in comparison.
	* tree-vectorizer.h (vect_get_vec_def_for_operand): Add VECTYPE
	arg.


diff --git a/gcc/expr.c b/gcc/expr.c
index 88da8cb..a624a34 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11320,6 +11320,40 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
   return 1;
 }
 
+/* Return a CONST_VECTOR rtx representing vector mask for
+   a VECTOR_CST of booleans.  */
+static rtx
+const_vector_mask_from_tree (tree exp)
+{
+  rtvec v;
+  unsigned i;
+  int units;
+  tree elt;
+  machine_mode inner, mode;
+
+  mode = TYPE_MODE (TREE_TYPE (exp));
+  units = GET_MODE_NUNITS (mode);
+  inner = GET_MODE_INNER (mode);
+
+  v = rtvec_alloc (units);
+
+  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
+    {
+      elt = VECTOR_CST_ELT (exp, i);
+
+      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
+      if (integer_zerop (elt))
+	RTVEC_ELT (v, i) = CONST0_RTX (inner);
+      else if (integer_onep (elt)
+	       || integer_minus_onep (elt))
+	RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
+      else
+	gcc_unreachable ();
+    }
+
+  return gen_rtx_CONST_VECTOR (mode, v);
+}
+
 /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
 static rtx
 const_vector_from_tree (tree exp)
@@ -11335,6 +11369,9 @@ const_vector_from_tree (tree exp)
   if (initializer_zerop (exp))
     return CONST0_RTX (mode);
 
+  if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
+      return const_vector_mask_from_tree (exp);
+
   units = GET_MODE_NUNITS (mode);
   inner = GET_MODE_INNER (mode);
 
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 6949c71..337ea7b 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1308,27 +1308,61 @@ vect_init_vector_1 (gimple *stmt, gimple *new_stmt, gimple_stmt_iterator *gsi)
 tree
 vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
 {
+  tree val_type = TREE_TYPE (val);
+  machine_mode mode = TYPE_MODE (type);
+  machine_mode val_mode = TYPE_MODE(val_type);
   tree new_var;
   gimple *init_stmt;
   tree vec_oprnd;
   tree new_temp;
 
   if (TREE_CODE (type) == VECTOR_TYPE
-      && TREE_CODE (TREE_TYPE (val)) != VECTOR_TYPE)
-    {
-      if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
+      && TREE_CODE (val_type) != VECTOR_TYPE)
+    {
+      /* Handle vector of bool represented as a vector of
+	 integers here rather than on expand because it is
+	 a default mask type for targets.  Vector mask is
+	 built in a following way:
+
+	 tmp = (int)val
+	 vec_tmp = {tmp, ..., tmp}
+	 vec_cst = VIEW_CONVERT_EXPR<vector(N) _Bool>(vec_tmp);  */
+      if (TREE_CODE (val_type) == BOOLEAN_TYPE
+	  && VECTOR_MODE_P (mode)
+	  && SCALAR_INT_MODE_P (GET_MODE_INNER (mode))
+	  && GET_MODE_INNER (mode) != val_mode)
 	{
-	  if (CONSTANT_CLASS_P (val))
-	    val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
-	  else
+	  unsigned size = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
+	  tree stype = build_nonstandard_integer_type (size, 1);
+	  tree vectype = get_vectype_for_scalar_type (stype);
+
+	  new_temp = make_ssa_name (stype);
+	  init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
+	  vect_init_vector_1 (stmt, init_stmt, gsi);
+
+	  val = make_ssa_name (vectype);
+	  new_temp = build_vector_from_val (vectype, new_temp);
+	  init_stmt = gimple_build_assign (val, new_temp);
+	  vect_init_vector_1 (stmt, init_stmt, gsi);
+
+	  val = build1 (VIEW_CONVERT_EXPR, type, val);
+	}
+      else
+	{
+	  if (!types_compatible_p (TREE_TYPE (type), val_type))
 	    {
-	      new_temp = make_ssa_name (TREE_TYPE (type));
-	      init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
-	      vect_init_vector_1 (stmt, init_stmt, gsi);
-	      val = new_temp;
+	      if (CONSTANT_CLASS_P (val))
+		val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
+	      else
+		{
+		  new_temp = make_ssa_name (TREE_TYPE (type));
+		  init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
+		  vect_init_vector_1 (stmt, init_stmt, gsi);
+		  val = new_temp;
+		}
 	    }
+	  val = build_vector_from_val (type, val);
 	}
-      val = build_vector_from_val (type, val);
     }
 
   new_var = vect_get_new_vect_var (type, vect_simple_var, "cst_");
@@ -1350,16 +1384,19 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
    STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
 
    In case OP is an invariant or constant, a new stmt that creates a vector def
-   needs to be introduced.  */
+   needs to be introduced.  VECTYPE may be used to specify a required type for
+   vector invariant.  */
 
 tree
-vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
+vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def,
+			      tree vectype)
 {
   tree vec_oprnd;
   gimple *vec_stmt;
   gimple *def_stmt;
   stmt_vec_info def_stmt_info = NULL;
   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+  tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
   unsigned int nunits;
   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
   tree def;
@@ -1403,7 +1440,14 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
     /* Case 1: operand is a constant.  */
     case vect_constant_def:
       {
-	vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+	if (vectype)
+	  vector_type = vectype;
+	else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
+		 && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
+	  vector_type = build_same_sized_truth_vector_type (stmt_vectype);
+	else
+	  vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+
 	gcc_assert (vector_type);
 	nunits = TYPE_VECTOR_SUBPARTS (vector_type);
 
@@ -1421,7 +1465,13 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
     /* Case 2: operand is defined outside the loop - loop invariant.  */
     case vect_external_def:
       {
-	vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
+	if (vectype)
+	  vector_type = vectype;
+	else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
+		 && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
+	  vector_type = build_same_sized_truth_vector_type (stmt_vectype);
+	else
+	  vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
 	gcc_assert (vector_type);
 
 	if (scalar_def)
@@ -7437,13 +7487,13 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
 	      gimple *gtemp;
 	      vec_cond_lhs =
 	      vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
-					    stmt, NULL);
+					    stmt, NULL, comp_vectype);
 	      vect_is_simple_use (TREE_OPERAND (cond_expr, 0), stmt,
 				  loop_vinfo, NULL, &gtemp, &def, &dts[0]);
 
 	      vec_cond_rhs =
 		vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
-						stmt, NULL);
+					      stmt, NULL, comp_vectype);
 	      vect_is_simple_use (TREE_OPERAND (cond_expr, 1), stmt,
 				  loop_vinfo, NULL, &gtemp, &def, &dts[1]);
 	      if (reduc_index == 1)
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 23a82ee..1a1e509 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1032,7 +1032,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
 extern void vect_finish_stmt_generation (gimple *, gimple *,
                                          gimple_stmt_iterator *);
 extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
-extern tree vect_get_vec_def_for_operand (tree, gimple *, tree *);
+extern tree vect_get_vec_def_for_operand (tree, gimple *, tree *, tree = NULL);
 extern tree vect_init_vector (gimple *, tree, tree,
                               gimple_stmt_iterator *);
 extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);

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

* Re: [vec-cmp, patch 4/6] Support vector mask invariants
  2015-10-08 15:12 [vec-cmp, patch 4/6] Support vector mask invariants Ilya Enkovich
@ 2015-10-13 13:54 ` Richard Biener
  2015-10-13 14:52   ` Ilya Enkovich
  0 siblings, 1 reply; 9+ messages in thread
From: Richard Biener @ 2015-10-13 13:54 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: GCC Patches

On Thu, Oct 8, 2015 at 5:11 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
> Hi,
>
> This patch adds a special handling of boolean vector invariants.  We need additional code to determine type of generated invariant.  For VEC_COND_EXPR case we even provide this type directly because statement vectype doesn't allow us to compute it.  Separate code is used to generate and expand such vectors.
>
> Thanks,
> Ilya
> --
> gcc/
>
> 2015-10-08  Ilya Enkovich  <enkovich.gnu@gmail.com>
>
>         * expr.c (const_vector_mask_from_tree): New.
>         (const_vector_from_tree): Use const_vector_mask_from_tree
>         for boolean vectors.
>         * tree-vect-stmts.c (vect_init_vector): Support boolean vector
>         invariants.
>         (vect_get_vec_def_for_operand): Add VECTYPE arg.
>         (vectorizable_condition): Directly provide vectype for invariants
>         used in comparison.
>         * tree-vectorizer.h (vect_get_vec_def_for_operand): Add VECTYPE
>         arg.
>
>
> diff --git a/gcc/expr.c b/gcc/expr.c
> index 88da8cb..a624a34 100644
> --- a/gcc/expr.c
> +++ b/gcc/expr.c
> @@ -11320,6 +11320,40 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
>    return 1;
>  }
>
> +/* Return a CONST_VECTOR rtx representing vector mask for
> +   a VECTOR_CST of booleans.  */
> +static rtx
> +const_vector_mask_from_tree (tree exp)
> +{
> +  rtvec v;
> +  unsigned i;
> +  int units;
> +  tree elt;
> +  machine_mode inner, mode;
> +
> +  mode = TYPE_MODE (TREE_TYPE (exp));
> +  units = GET_MODE_NUNITS (mode);
> +  inner = GET_MODE_INNER (mode);
> +
> +  v = rtvec_alloc (units);
> +
> +  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
> +    {
> +      elt = VECTOR_CST_ELT (exp, i);
> +
> +      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
> +      if (integer_zerop (elt))
> +       RTVEC_ELT (v, i) = CONST0_RTX (inner);
> +      else if (integer_onep (elt)
> +              || integer_minus_onep (elt))
> +       RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
> +      else
> +       gcc_unreachable ();
> +    }
> +
> +  return gen_rtx_CONST_VECTOR (mode, v);
> +}
> +
>  /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
>  static rtx
>  const_vector_from_tree (tree exp)
> @@ -11335,6 +11369,9 @@ const_vector_from_tree (tree exp)
>    if (initializer_zerop (exp))
>      return CONST0_RTX (mode);
>
> +  if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
> +      return const_vector_mask_from_tree (exp);
> +
>    units = GET_MODE_NUNITS (mode);
>    inner = GET_MODE_INNER (mode);
>
> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
> index 6949c71..337ea7b 100644
> --- a/gcc/tree-vect-stmts.c
> +++ b/gcc/tree-vect-stmts.c
> @@ -1308,27 +1308,61 @@ vect_init_vector_1 (gimple *stmt, gimple *new_stmt, gimple_stmt_iterator *gsi)
>  tree
>  vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>  {
> +  tree val_type = TREE_TYPE (val);
> +  machine_mode mode = TYPE_MODE (type);
> +  machine_mode val_mode = TYPE_MODE(val_type);
>    tree new_var;
>    gimple *init_stmt;
>    tree vec_oprnd;
>    tree new_temp;
>
>    if (TREE_CODE (type) == VECTOR_TYPE
> -      && TREE_CODE (TREE_TYPE (val)) != VECTOR_TYPE)
> -    {
> -      if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
> +      && TREE_CODE (val_type) != VECTOR_TYPE)
> +    {
> +      /* Handle vector of bool represented as a vector of
> +        integers here rather than on expand because it is
> +        a default mask type for targets.  Vector mask is
> +        built in a following way:
> +
> +        tmp = (int)val
> +        vec_tmp = {tmp, ..., tmp}
> +        vec_cst = VIEW_CONVERT_EXPR<vector(N) _Bool>(vec_tmp);  */
> +      if (TREE_CODE (val_type) == BOOLEAN_TYPE
> +         && VECTOR_MODE_P (mode)
> +         && SCALAR_INT_MODE_P (GET_MODE_INNER (mode))
> +         && GET_MODE_INNER (mode) != val_mode)
>         {
> -         if (CONSTANT_CLASS_P (val))
> -           val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
> -         else
> +         unsigned size = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
> +         tree stype = build_nonstandard_integer_type (size, 1);
> +         tree vectype = get_vectype_for_scalar_type (stype);
> +
> +         new_temp = make_ssa_name (stype);
> +         init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
> +         vect_init_vector_1 (stmt, init_stmt, gsi);
> +
> +         val = make_ssa_name (vectype);
> +         new_temp = build_vector_from_val (vectype, new_temp);
> +         init_stmt = gimple_build_assign (val, new_temp);
> +         vect_init_vector_1 (stmt, init_stmt, gsi);
> +
> +         val = build1 (VIEW_CONVERT_EXPR, type, val);

So I don't quite understand - why don't we want to build

   tmp = (bool-element-type)val;
   vec_cst = {tmp, tmp, tmp ... };

?

> +       }
> +      else
> +       {
> +         if (!types_compatible_p (TREE_TYPE (type), val_type))
>             {
> -             new_temp = make_ssa_name (TREE_TYPE (type));
> -             init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
> -             vect_init_vector_1 (stmt, init_stmt, gsi);
> -             val = new_temp;
> +             if (CONSTANT_CLASS_P (val))
> +               val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
> +             else
> +               {
> +                 new_temp = make_ssa_name (TREE_TYPE (type));
> +                 init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
> +                 vect_init_vector_1 (stmt, init_stmt, gsi);
> +                 val = new_temp;
> +               }
>             }
> +         val = build_vector_from_val (type, val);
>         }
> -      val = build_vector_from_val (type, val);
>      }
>
>    new_var = vect_get_new_vect_var (type, vect_simple_var, "cst_");
> @@ -1350,16 +1384,19 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>     STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
>
>     In case OP is an invariant or constant, a new stmt that creates a vector def
> -   needs to be introduced.  */
> +   needs to be introduced.  VECTYPE may be used to specify a required type for
> +   vector invariant.  */
>
>  tree
> -vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
> +vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def,
> +                             tree vectype)
>  {
>    tree vec_oprnd;
>    gimple *vec_stmt;
>    gimple *def_stmt;
>    stmt_vec_info def_stmt_info = NULL;
>    stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
> +  tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
>    unsigned int nunits;
>    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
>    tree def;
> @@ -1403,7 +1440,14 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>      /* Case 1: operand is a constant.  */
>      case vect_constant_def:
>        {
> -       vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
> +       if (vectype)
> +         vector_type = vectype;
> +       else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
> +                && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
> +         vector_type = build_same_sized_truth_vector_type (stmt_vectype);
> +       else
> +         vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));

Rather than this...

> +
>         gcc_assert (vector_type);
>         nunits = TYPE_VECTOR_SUBPARTS (vector_type);
>
> @@ -1421,7 +1465,13 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>      /* Case 2: operand is defined outside the loop - loop invariant.  */
>      case vect_external_def:
>        {
> -       vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
> +       if (vectype)
> +         vector_type = vectype;
> +       else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
> +                && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
> +         vector_type = build_same_sized_truth_vector_type (stmt_vectype);
> +       else
> +         vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
>         gcc_assert (vector_type);

and this ...

>         if (scalar_def)
> @@ -7437,13 +7487,13 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
>               gimple *gtemp;
>               vec_cond_lhs =
>               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
> -                                           stmt, NULL);
> +                                           stmt, NULL, comp_vectype);
>               vect_is_simple_use (TREE_OPERAND (cond_expr, 0), stmt,
>                                   loop_vinfo, NULL, &gtemp, &def, &dts[0]);
>
>               vec_cond_rhs =
>                 vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
> -                                               stmt, NULL);
> +                                             stmt, NULL, comp_vectype);
>               vect_is_simple_use (TREE_OPERAND (cond_expr, 1), stmt,
>                                   loop_vinfo, NULL, &gtemp, &def, &dts[1]);

I'd simply open-code this here?

>               if (reduc_index == 1)
> diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
> index 23a82ee..1a1e509 100644
> --- a/gcc/tree-vectorizer.h
> +++ b/gcc/tree-vectorizer.h
> @@ -1032,7 +1032,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
>  extern void vect_finish_stmt_generation (gimple *, gimple *,
>                                           gimple_stmt_iterator *);
>  extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
> -extern tree vect_get_vec_def_for_operand (tree, gimple *, tree *);
> +extern tree vect_get_vec_def_for_operand (tree, gimple *, tree *, tree = NULL);
>  extern tree vect_init_vector (gimple *, tree, tree,
>                                gimple_stmt_iterator *);
>  extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);

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

* Re: [vec-cmp, patch 4/6] Support vector mask invariants
  2015-10-13 13:54 ` Richard Biener
@ 2015-10-13 14:52   ` Ilya Enkovich
  2015-10-14  8:49     ` Richard Biener
  0 siblings, 1 reply; 9+ messages in thread
From: Ilya Enkovich @ 2015-10-13 14:52 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

2015-10-13 16:54 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
> On Thu, Oct 8, 2015 at 5:11 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
>> Hi,
>>
>> This patch adds a special handling of boolean vector invariants.  We need additional code to determine type of generated invariant.  For VEC_COND_EXPR case we even provide this type directly because statement vectype doesn't allow us to compute it.  Separate code is used to generate and expand such vectors.
>>
>> Thanks,
>> Ilya
>> --
>> gcc/
>>
>> 2015-10-08  Ilya Enkovich  <enkovich.gnu@gmail.com>
>>
>>         * expr.c (const_vector_mask_from_tree): New.
>>         (const_vector_from_tree): Use const_vector_mask_from_tree
>>         for boolean vectors.
>>         * tree-vect-stmts.c (vect_init_vector): Support boolean vector
>>         invariants.
>>         (vect_get_vec_def_for_operand): Add VECTYPE arg.
>>         (vectorizable_condition): Directly provide vectype for invariants
>>         used in comparison.
>>         * tree-vectorizer.h (vect_get_vec_def_for_operand): Add VECTYPE
>>         arg.
>>
>>
>> diff --git a/gcc/expr.c b/gcc/expr.c
>> index 88da8cb..a624a34 100644
>> --- a/gcc/expr.c
>> +++ b/gcc/expr.c
>> @@ -11320,6 +11320,40 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
>>    return 1;
>>  }
>>
>> +/* Return a CONST_VECTOR rtx representing vector mask for
>> +   a VECTOR_CST of booleans.  */
>> +static rtx
>> +const_vector_mask_from_tree (tree exp)
>> +{
>> +  rtvec v;
>> +  unsigned i;
>> +  int units;
>> +  tree elt;
>> +  machine_mode inner, mode;
>> +
>> +  mode = TYPE_MODE (TREE_TYPE (exp));
>> +  units = GET_MODE_NUNITS (mode);
>> +  inner = GET_MODE_INNER (mode);
>> +
>> +  v = rtvec_alloc (units);
>> +
>> +  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
>> +    {
>> +      elt = VECTOR_CST_ELT (exp, i);
>> +
>> +      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
>> +      if (integer_zerop (elt))
>> +       RTVEC_ELT (v, i) = CONST0_RTX (inner);
>> +      else if (integer_onep (elt)
>> +              || integer_minus_onep (elt))
>> +       RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
>> +      else
>> +       gcc_unreachable ();
>> +    }
>> +
>> +  return gen_rtx_CONST_VECTOR (mode, v);
>> +}
>> +
>>  /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
>>  static rtx
>>  const_vector_from_tree (tree exp)
>> @@ -11335,6 +11369,9 @@ const_vector_from_tree (tree exp)
>>    if (initializer_zerop (exp))
>>      return CONST0_RTX (mode);
>>
>> +  if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
>> +      return const_vector_mask_from_tree (exp);
>> +
>>    units = GET_MODE_NUNITS (mode);
>>    inner = GET_MODE_INNER (mode);
>>
>> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
>> index 6949c71..337ea7b 100644
>> --- a/gcc/tree-vect-stmts.c
>> +++ b/gcc/tree-vect-stmts.c
>> @@ -1308,27 +1308,61 @@ vect_init_vector_1 (gimple *stmt, gimple *new_stmt, gimple_stmt_iterator *gsi)
>>  tree
>>  vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>>  {
>> +  tree val_type = TREE_TYPE (val);
>> +  machine_mode mode = TYPE_MODE (type);
>> +  machine_mode val_mode = TYPE_MODE(val_type);
>>    tree new_var;
>>    gimple *init_stmt;
>>    tree vec_oprnd;
>>    tree new_temp;
>>
>>    if (TREE_CODE (type) == VECTOR_TYPE
>> -      && TREE_CODE (TREE_TYPE (val)) != VECTOR_TYPE)
>> -    {
>> -      if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
>> +      && TREE_CODE (val_type) != VECTOR_TYPE)
>> +    {
>> +      /* Handle vector of bool represented as a vector of
>> +        integers here rather than on expand because it is
>> +        a default mask type for targets.  Vector mask is
>> +        built in a following way:
>> +
>> +        tmp = (int)val
>> +        vec_tmp = {tmp, ..., tmp}
>> +        vec_cst = VIEW_CONVERT_EXPR<vector(N) _Bool>(vec_tmp);  */
>> +      if (TREE_CODE (val_type) == BOOLEAN_TYPE
>> +         && VECTOR_MODE_P (mode)
>> +         && SCALAR_INT_MODE_P (GET_MODE_INNER (mode))
>> +         && GET_MODE_INNER (mode) != val_mode)
>>         {
>> -         if (CONSTANT_CLASS_P (val))
>> -           val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
>> -         else
>> +         unsigned size = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
>> +         tree stype = build_nonstandard_integer_type (size, 1);
>> +         tree vectype = get_vectype_for_scalar_type (stype);
>> +
>> +         new_temp = make_ssa_name (stype);
>> +         init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
>> +         vect_init_vector_1 (stmt, init_stmt, gsi);
>> +
>> +         val = make_ssa_name (vectype);
>> +         new_temp = build_vector_from_val (vectype, new_temp);
>> +         init_stmt = gimple_build_assign (val, new_temp);
>> +         vect_init_vector_1 (stmt, init_stmt, gsi);
>> +
>> +         val = build1 (VIEW_CONVERT_EXPR, type, val);
>l
> So I don't quite understand - why don't we want to build
>
>    tmp = (bool-element-type)val;
>    vec_cst = {tmp, tmp, tmp ... };
>
> ?

This code was written at a time boolean vector elements always had
bitsize 1. I'll rework it in accordance with new boolean types.

>
>> +       }
>> +      else
>> +       {
>> +         if (!types_compatible_p (TREE_TYPE (type), val_type))
>>             {
>> -             new_temp = make_ssa_name (TREE_TYPE (type));
>> -             init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
>> -             vect_init_vector_1 (stmt, init_stmt, gsi);
>> -             val = new_temp;
>> +             if (CONSTANT_CLASS_P (val))
>> +               val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
>> +             else
>> +               {
>> +                 new_temp = make_ssa_name (TREE_TYPE (type));
>> +                 init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
>> +                 vect_init_vector_1 (stmt, init_stmt, gsi);
>> +                 val = new_temp;
>> +               }
>>             }
>> +         val = build_vector_from_val (type, val);
>>         }
>> -      val = build_vector_from_val (type, val);
>>      }
>>
>>    new_var = vect_get_new_vect_var (type, vect_simple_var, "cst_");
>> @@ -1350,16 +1384,19 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>>     STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
>>
>>     In case OP is an invariant or constant, a new stmt that creates a vector def
>> -   needs to be introduced.  */
>> +   needs to be introduced.  VECTYPE may be used to specify a required type for
>> +   vector invariant.  */
>>
>>  tree
>> -vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>> +vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def,
>> +                             tree vectype)
>>  {
>>    tree vec_oprnd;
>>    gimple *vec_stmt;
>>    gimple *def_stmt;
>>    stmt_vec_info def_stmt_info = NULL;
>>    stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
>> +  tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
>>    unsigned int nunits;
>>    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
>>    tree def;
>> @@ -1403,7 +1440,14 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>>      /* Case 1: operand is a constant.  */
>>      case vect_constant_def:
>>        {
>> -       vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
>> +       if (vectype)
>> +         vector_type = vectype;
>> +       else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
>> +                && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
>> +         vector_type = build_same_sized_truth_vector_type (stmt_vectype);
>> +       else
>> +         vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
>
> Rather than this...
>
>> +
>>         gcc_assert (vector_type);
>>         nunits = TYPE_VECTOR_SUBPARTS (vector_type);
>>
>> @@ -1421,7 +1465,13 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>>      /* Case 2: operand is defined outside the loop - loop invariant.  */
>>      case vect_external_def:
>>        {
>> -       vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
>> +       if (vectype)
>> +         vector_type = vectype;
>> +       else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
>> +                && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
>> +         vector_type = build_same_sized_truth_vector_type (stmt_vectype);
>> +       else
>> +         vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
>>         gcc_assert (vector_type);
>
> and this ...
>
>>         if (scalar_def)
>> @@ -7437,13 +7487,13 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
>>               gimple *gtemp;
>>               vec_cond_lhs =
>>               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
>> -                                           stmt, NULL);
>> +                                           stmt, NULL, comp_vectype);
>>               vect_is_simple_use (TREE_OPERAND (cond_expr, 0), stmt,
>>                                   loop_vinfo, NULL, &gtemp, &def, &dts[0]);
>>
>>               vec_cond_rhs =
>>                 vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
>> -                                               stmt, NULL);
>> +                                             stmt, NULL, comp_vectype);
>>               vect_is_simple_use (TREE_OPERAND (cond_expr, 1), stmt,
>>                                   loop_vinfo, NULL, &gtemp, &def, &dts[1]);
>
> I'd simply open-code this here?

I don't understand what you mean. vect_get_vec_def_for_operand has two
changes made.
1. For boolean invariants use build_same_sized_truth_vector_type
instead of get_vectype_for_scalar_type in case statement produces a
boolean vector. This covers cases when we use invariants in
comparison, AND, IOR, XOR.
2. COND_EXPR is an exception because it has built-in boolean vector
result not reflected in its vecinfo. Thus I added additional operand
for vect_get_vec_def_for_operand to directly specify vectype for
vector definition in case it is a loop invariant.
So what do you propose to do with these changes?

Thanks,
Ilya

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

* Re: [vec-cmp, patch 4/6] Support vector mask invariants
  2015-10-13 14:52   ` Ilya Enkovich
@ 2015-10-14  8:49     ` Richard Biener
  2015-10-14 10:50       ` Ilya Enkovich
  0 siblings, 1 reply; 9+ messages in thread
From: Richard Biener @ 2015-10-14  8:49 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: GCC Patches

On Tue, Oct 13, 2015 at 4:52 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
> 2015-10-13 16:54 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
>> On Thu, Oct 8, 2015 at 5:11 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
>>> Hi,
>>>
>>> This patch adds a special handling of boolean vector invariants.  We need additional code to determine type of generated invariant.  For VEC_COND_EXPR case we even provide this type directly because statement vectype doesn't allow us to compute it.  Separate code is used to generate and expand such vectors.
>>>
>>> Thanks,
>>> Ilya
>>> --
>>> gcc/
>>>
>>> 2015-10-08  Ilya Enkovich  <enkovich.gnu@gmail.com>
>>>
>>>         * expr.c (const_vector_mask_from_tree): New.
>>>         (const_vector_from_tree): Use const_vector_mask_from_tree
>>>         for boolean vectors.
>>>         * tree-vect-stmts.c (vect_init_vector): Support boolean vector
>>>         invariants.
>>>         (vect_get_vec_def_for_operand): Add VECTYPE arg.
>>>         (vectorizable_condition): Directly provide vectype for invariants
>>>         used in comparison.
>>>         * tree-vectorizer.h (vect_get_vec_def_for_operand): Add VECTYPE
>>>         arg.
>>>
>>>
>>> diff --git a/gcc/expr.c b/gcc/expr.c
>>> index 88da8cb..a624a34 100644
>>> --- a/gcc/expr.c
>>> +++ b/gcc/expr.c
>>> @@ -11320,6 +11320,40 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
>>>    return 1;
>>>  }
>>>
>>> +/* Return a CONST_VECTOR rtx representing vector mask for
>>> +   a VECTOR_CST of booleans.  */
>>> +static rtx
>>> +const_vector_mask_from_tree (tree exp)
>>> +{
>>> +  rtvec v;
>>> +  unsigned i;
>>> +  int units;
>>> +  tree elt;
>>> +  machine_mode inner, mode;
>>> +
>>> +  mode = TYPE_MODE (TREE_TYPE (exp));
>>> +  units = GET_MODE_NUNITS (mode);
>>> +  inner = GET_MODE_INNER (mode);
>>> +
>>> +  v = rtvec_alloc (units);
>>> +
>>> +  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
>>> +    {
>>> +      elt = VECTOR_CST_ELT (exp, i);
>>> +
>>> +      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
>>> +      if (integer_zerop (elt))
>>> +       RTVEC_ELT (v, i) = CONST0_RTX (inner);
>>> +      else if (integer_onep (elt)
>>> +              || integer_minus_onep (elt))
>>> +       RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
>>> +      else
>>> +       gcc_unreachable ();
>>> +    }
>>> +
>>> +  return gen_rtx_CONST_VECTOR (mode, v);
>>> +}
>>> +
>>>  /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
>>>  static rtx
>>>  const_vector_from_tree (tree exp)
>>> @@ -11335,6 +11369,9 @@ const_vector_from_tree (tree exp)
>>>    if (initializer_zerop (exp))
>>>      return CONST0_RTX (mode);
>>>
>>> +  if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
>>> +      return const_vector_mask_from_tree (exp);
>>> +
>>>    units = GET_MODE_NUNITS (mode);
>>>    inner = GET_MODE_INNER (mode);
>>>
>>> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
>>> index 6949c71..337ea7b 100644
>>> --- a/gcc/tree-vect-stmts.c
>>> +++ b/gcc/tree-vect-stmts.c
>>> @@ -1308,27 +1308,61 @@ vect_init_vector_1 (gimple *stmt, gimple *new_stmt, gimple_stmt_iterator *gsi)
>>>  tree
>>>  vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>>>  {
>>> +  tree val_type = TREE_TYPE (val);
>>> +  machine_mode mode = TYPE_MODE (type);
>>> +  machine_mode val_mode = TYPE_MODE(val_type);
>>>    tree new_var;
>>>    gimple *init_stmt;
>>>    tree vec_oprnd;
>>>    tree new_temp;
>>>
>>>    if (TREE_CODE (type) == VECTOR_TYPE
>>> -      && TREE_CODE (TREE_TYPE (val)) != VECTOR_TYPE)
>>> -    {
>>> -      if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
>>> +      && TREE_CODE (val_type) != VECTOR_TYPE)
>>> +    {
>>> +      /* Handle vector of bool represented as a vector of
>>> +        integers here rather than on expand because it is
>>> +        a default mask type for targets.  Vector mask is
>>> +        built in a following way:
>>> +
>>> +        tmp = (int)val
>>> +        vec_tmp = {tmp, ..., tmp}
>>> +        vec_cst = VIEW_CONVERT_EXPR<vector(N) _Bool>(vec_tmp);  */
>>> +      if (TREE_CODE (val_type) == BOOLEAN_TYPE
>>> +         && VECTOR_MODE_P (mode)
>>> +         && SCALAR_INT_MODE_P (GET_MODE_INNER (mode))
>>> +         && GET_MODE_INNER (mode) != val_mode)
>>>         {
>>> -         if (CONSTANT_CLASS_P (val))
>>> -           val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
>>> -         else
>>> +         unsigned size = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
>>> +         tree stype = build_nonstandard_integer_type (size, 1);
>>> +         tree vectype = get_vectype_for_scalar_type (stype);
>>> +
>>> +         new_temp = make_ssa_name (stype);
>>> +         init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
>>> +         vect_init_vector_1 (stmt, init_stmt, gsi);
>>> +
>>> +         val = make_ssa_name (vectype);
>>> +         new_temp = build_vector_from_val (vectype, new_temp);
>>> +         init_stmt = gimple_build_assign (val, new_temp);
>>> +         vect_init_vector_1 (stmt, init_stmt, gsi);
>>> +
>>> +         val = build1 (VIEW_CONVERT_EXPR, type, val);
>>l
>> So I don't quite understand - why don't we want to build
>>
>>    tmp = (bool-element-type)val;
>>    vec_cst = {tmp, tmp, tmp ... };
>>
>> ?
>
> This code was written at a time boolean vector elements always had
> bitsize 1. I'll rework it in accordance with new boolean types.
>
>>
>>> +       }
>>> +      else
>>> +       {
>>> +         if (!types_compatible_p (TREE_TYPE (type), val_type))
>>>             {
>>> -             new_temp = make_ssa_name (TREE_TYPE (type));
>>> -             init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
>>> -             vect_init_vector_1 (stmt, init_stmt, gsi);
>>> -             val = new_temp;
>>> +             if (CONSTANT_CLASS_P (val))
>>> +               val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
>>> +             else
>>> +               {
>>> +                 new_temp = make_ssa_name (TREE_TYPE (type));
>>> +                 init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
>>> +                 vect_init_vector_1 (stmt, init_stmt, gsi);
>>> +                 val = new_temp;
>>> +               }
>>>             }
>>> +         val = build_vector_from_val (type, val);
>>>         }
>>> -      val = build_vector_from_val (type, val);
>>>      }
>>>
>>>    new_var = vect_get_new_vect_var (type, vect_simple_var, "cst_");
>>> @@ -1350,16 +1384,19 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>>>     STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
>>>
>>>     In case OP is an invariant or constant, a new stmt that creates a vector def
>>> -   needs to be introduced.  */
>>> +   needs to be introduced.  VECTYPE may be used to specify a required type for
>>> +   vector invariant.  */
>>>
>>>  tree
>>> -vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>>> +vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def,
>>> +                             tree vectype)
>>>  {
>>>    tree vec_oprnd;
>>>    gimple *vec_stmt;
>>>    gimple *def_stmt;
>>>    stmt_vec_info def_stmt_info = NULL;
>>>    stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
>>> +  tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
>>>    unsigned int nunits;
>>>    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
>>>    tree def;
>>> @@ -1403,7 +1440,14 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>>>      /* Case 1: operand is a constant.  */
>>>      case vect_constant_def:
>>>        {
>>> -       vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
>>> +       if (vectype)
>>> +         vector_type = vectype;
>>> +       else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
>>> +                && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
>>> +         vector_type = build_same_sized_truth_vector_type (stmt_vectype);
>>> +       else
>>> +         vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
>>
>> Rather than this...
>>
>>> +
>>>         gcc_assert (vector_type);
>>>         nunits = TYPE_VECTOR_SUBPARTS (vector_type);
>>>
>>> @@ -1421,7 +1465,13 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>>>      /* Case 2: operand is defined outside the loop - loop invariant.  */
>>>      case vect_external_def:
>>>        {
>>> -       vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
>>> +       if (vectype)
>>> +         vector_type = vectype;
>>> +       else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
>>> +                && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
>>> +         vector_type = build_same_sized_truth_vector_type (stmt_vectype);
>>> +       else
>>> +         vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
>>>         gcc_assert (vector_type);
>>
>> and this ...
>>
>>>         if (scalar_def)
>>> @@ -7437,13 +7487,13 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
>>>               gimple *gtemp;
>>>               vec_cond_lhs =
>>>               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
>>> -                                           stmt, NULL);
>>> +                                           stmt, NULL, comp_vectype);
>>>               vect_is_simple_use (TREE_OPERAND (cond_expr, 0), stmt,
>>>                                   loop_vinfo, NULL, &gtemp, &def, &dts[0]);
>>>
>>>               vec_cond_rhs =
>>>                 vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
>>> -                                               stmt, NULL);
>>> +                                             stmt, NULL, comp_vectype);
>>>               vect_is_simple_use (TREE_OPERAND (cond_expr, 1), stmt,
>>>                                   loop_vinfo, NULL, &gtemp, &def, &dts[1]);
>>
>> I'd simply open-code this here?
>
> I don't understand what you mean. vect_get_vec_def_for_operand has two
> changes made.
> 1. For boolean invariants use build_same_sized_truth_vector_type
> instead of get_vectype_for_scalar_type in case statement produces a
> boolean vector. This covers cases when we use invariants in
> comparison, AND, IOR, XOR.

Yes, I understand we need this special-casing to differentiate between
the vector type
used for boolean-typed loads/stores and the type for boolean typed constants.
What happens if we mix them btw, like with

  _Bool b = bools[i];
  _Bool c = b || d;
  ...

?

> 2. COND_EXPR is an exception because it has built-in boolean vector
> result not reflected in its vecinfo. Thus I added additional operand
> for vect_get_vec_def_for_operand to directly specify vectype for
> vector definition in case it is a loop invariant.
> So what do you propose to do with these changes?

This is the change I don't like and don't see why we need it.  It works today
and the comparison operands should be of appropriate type already?

Richard.

> Thanks,
> Ilya

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

* Re: [vec-cmp, patch 4/6] Support vector mask invariants
  2015-10-14  8:49     ` Richard Biener
@ 2015-10-14 10:50       ` Ilya Enkovich
  2015-10-14 16:14         ` Ilya Enkovich
  0 siblings, 1 reply; 9+ messages in thread
From: Ilya Enkovich @ 2015-10-14 10:50 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

2015-10-14 11:49 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
> On Tue, Oct 13, 2015 at 4:52 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
>> I don't understand what you mean. vect_get_vec_def_for_operand has two
>> changes made.
>> 1. For boolean invariants use build_same_sized_truth_vector_type
>> instead of get_vectype_for_scalar_type in case statement produces a
>> boolean vector. This covers cases when we use invariants in
>> comparison, AND, IOR, XOR.
>
> Yes, I understand we need this special-casing to differentiate between
> the vector type
> used for boolean-typed loads/stores and the type for boolean typed constants.
> What happens if we mix them btw, like with
>
>   _Bool b = bools[i];
>   _Bool c = b || d;
>   ...
>
> ?

Here both statements should get vector of char as a vectype and we
never go VECTOR_BOOLEAN_TYPE_P way for them

>
>> 2. COND_EXPR is an exception because it has built-in boolean vector
>> result not reflected in its vecinfo. Thus I added additional operand
>> for vect_get_vec_def_for_operand to directly specify vectype for
>> vector definition in case it is a loop invariant.
>> So what do you propose to do with these changes?
>
> This is the change I don't like and don't see why we need it.  It works today
> and the comparison operands should be of appropriate type already?

Today it works because we always create vector of integer constant.
With boolean vectors it may be either integer vector or boolean vector
depending on context. Consider:

_Bool _1;
int _2;

_2 = _1 != 0 ? 0 : 1

We have two zero constants here requiring different vectypes.

Ilya

>
> Richard.
>
>> Thanks,
>> Ilya

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

* Re: [vec-cmp, patch 4/6] Support vector mask invariants
  2015-10-14 10:50       ` Ilya Enkovich
@ 2015-10-14 16:14         ` Ilya Enkovich
  2015-10-26 15:25           ` Richard Biener
  0 siblings, 1 reply; 9+ messages in thread
From: Ilya Enkovich @ 2015-10-14 16:14 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

On 14 Oct 13:50, Ilya Enkovich wrote:
> 2015-10-14 11:49 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
> > On Tue, Oct 13, 2015 at 4:52 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
> >> I don't understand what you mean. vect_get_vec_def_for_operand has two
> >> changes made.
> >> 1. For boolean invariants use build_same_sized_truth_vector_type
> >> instead of get_vectype_for_scalar_type in case statement produces a
> >> boolean vector. This covers cases when we use invariants in
> >> comparison, AND, IOR, XOR.
> >
> > Yes, I understand we need this special-casing to differentiate between
> > the vector type
> > used for boolean-typed loads/stores and the type for boolean typed constants.
> > What happens if we mix them btw, like with
> >
> >   _Bool b = bools[i];
> >   _Bool c = b || d;
> >   ...
> >
> > ?
> 
> Here both statements should get vector of char as a vectype and we
> never go VECTOR_BOOLEAN_TYPE_P way for them
> 
> >
> >> 2. COND_EXPR is an exception because it has built-in boolean vector
> >> result not reflected in its vecinfo. Thus I added additional operand
> >> for vect_get_vec_def_for_operand to directly specify vectype for
> >> vector definition in case it is a loop invariant.
> >> So what do you propose to do with these changes?
> >
> > This is the change I don't like and don't see why we need it.  It works today
> > and the comparison operands should be of appropriate type already?
> 
> Today it works because we always create vector of integer constant.
> With boolean vectors it may be either integer vector or boolean vector
> depending on context. Consider:
> 
> _Bool _1;
> int _2;
> 
> _2 = _1 != 0 ? 0 : 1
> 
> We have two zero constants here requiring different vectypes.
> 
> Ilya
> 
> >
> > Richard.
> >
> >> Thanks,
> >> Ilya

Here is an updated patch version.

Thanks,
Ilya
--
gcc/

2015-10-14  Ilya Enkovich  <enkovich.gnu@gmail.com>

	* expr.c (const_vector_mask_from_tree): New.
	(const_vector_from_tree): Use const_vector_mask_from_tree
	for boolean vectors.
	* tree-vect-stmts.c (vect_init_vector): Support boolean vector
	invariants.
	(vect_get_vec_def_for_operand): Add VECTYPE arg.
	(vectorizable_condition): Directly provide vectype for invariants
	used in comparison.
	* tree-vectorizer.h (vect_get_vec_def_for_operand): Add VECTYPE
	arg.


diff --git a/gcc/expr.c b/gcc/expr.c
index b5ff598..ab25d1a 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11344,6 +11344,40 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
   return 1;
 }
 
+/* Return a CONST_VECTOR rtx representing vector mask for
+   a VECTOR_CST of booleans.  */
+static rtx
+const_vector_mask_from_tree (tree exp)
+{
+  rtvec v;
+  unsigned i;
+  int units;
+  tree elt;
+  machine_mode inner, mode;
+
+  mode = TYPE_MODE (TREE_TYPE (exp));
+  units = GET_MODE_NUNITS (mode);
+  inner = GET_MODE_INNER (mode);
+
+  v = rtvec_alloc (units);
+
+  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
+    {
+      elt = VECTOR_CST_ELT (exp, i);
+
+      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
+      if (integer_zerop (elt))
+	RTVEC_ELT (v, i) = CONST0_RTX (inner);
+      else if (integer_onep (elt)
+	       || integer_minus_onep (elt))
+	RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
+      else
+	gcc_unreachable ();
+    }
+
+  return gen_rtx_CONST_VECTOR (mode, v);
+}
+
 /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
 static rtx
 const_vector_from_tree (tree exp)
@@ -11359,6 +11393,9 @@ const_vector_from_tree (tree exp)
   if (initializer_zerop (exp))
     return CONST0_RTX (mode);
 
+  if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
+    return const_vector_mask_from_tree (exp);
+
   units = GET_MODE_NUNITS (mode);
   inner = GET_MODE_INNER (mode);
 
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 6a52895..01168ae 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1308,7 +1308,22 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
       if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
 	{
 	  if (CONSTANT_CLASS_P (val))
-	    val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
+	    {
+	      /* Can't use VIEW_CONVERT_EXPR for booleans because
+		 of possibly different sizes of scalar value and
+		 vector element.  */
+	      if (VECTOR_BOOLEAN_TYPE_P (type))
+		{
+		  if (integer_zerop (val))
+		    val = build_int_cst (TREE_TYPE (type), 0);
+		  else if (integer_onep (val))
+		    val = build_int_cst (TREE_TYPE (type), 1);
+		  else
+		    gcc_unreachable ();
+		}
+	      else
+		val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
+	    }
 	  else
 	    {
 	      new_temp = make_ssa_name (TREE_TYPE (type));
@@ -1339,16 +1354,19 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
    STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
 
    In case OP is an invariant or constant, a new stmt that creates a vector def
-   needs to be introduced.  */
+   needs to be introduced.  VECTYPE may be used to specify a required type for
+   vector invariant.  */
 
 tree
-vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
+vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def,
+			      tree vectype)
 {
   tree vec_oprnd;
   gimple *vec_stmt;
   gimple *def_stmt;
   stmt_vec_info def_stmt_info = NULL;
   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+  tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
   unsigned int nunits;
   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
   tree def;
@@ -1392,7 +1410,14 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
     /* Case 1: operand is a constant.  */
     case vect_constant_def:
       {
-	vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+	if (vectype)
+	  vector_type = vectype;
+	else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
+		 && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
+	  vector_type = build_same_sized_truth_vector_type (stmt_vectype);
+	else
+	  vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+
 	gcc_assert (vector_type);
 	nunits = TYPE_VECTOR_SUBPARTS (vector_type);
 
@@ -1410,7 +1435,13 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
     /* Case 2: operand is defined outside the loop - loop invariant.  */
     case vect_external_def:
       {
-	vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
+	if (vectype)
+	  vector_type = vectype;
+	else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
+		 && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
+	  vector_type = build_same_sized_truth_vector_type (stmt_vectype);
+	else
+	  vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
 	gcc_assert (vector_type);
 
 	if (scalar_def)
@@ -7428,13 +7459,13 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
 	      gimple *gtemp;
 	      vec_cond_lhs =
 	      vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
-					    stmt, NULL);
+					    stmt, NULL, comp_vectype);
 	      vect_is_simple_use (TREE_OPERAND (cond_expr, 0), stmt,
 				  loop_vinfo, &gtemp, &def, &dts[0]);
 
 	      vec_cond_rhs =
 		vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
-						stmt, NULL);
+					      stmt, NULL, comp_vectype);
 	      vect_is_simple_use (TREE_OPERAND (cond_expr, 1), stmt,
 				  loop_vinfo, &gtemp, &def, &dts[1]);
 	      if (reduc_index == 1)
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index f8d1e97..8eca7be 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -994,7 +994,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
 extern void vect_finish_stmt_generation (gimple *, gimple *,
                                          gimple_stmt_iterator *);
 extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
-extern tree vect_get_vec_def_for_operand (tree, gimple *, tree *);
+extern tree vect_get_vec_def_for_operand (tree, gimple *, tree *, tree = NULL);
 extern tree vect_init_vector (gimple *, tree, tree,
                               gimple_stmt_iterator *);
 extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);

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

* Re: [vec-cmp, patch 4/6] Support vector mask invariants
  2015-10-14 16:14         ` Ilya Enkovich
@ 2015-10-26 15:25           ` Richard Biener
  2015-11-09 12:11             ` Ilya Enkovich
  0 siblings, 1 reply; 9+ messages in thread
From: Richard Biener @ 2015-10-26 15:25 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: GCC Patches

On Wed, Oct 14, 2015 at 6:13 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
> On 14 Oct 13:50, Ilya Enkovich wrote:
>> 2015-10-14 11:49 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
>> > On Tue, Oct 13, 2015 at 4:52 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
>> >> I don't understand what you mean. vect_get_vec_def_for_operand has two
>> >> changes made.
>> >> 1. For boolean invariants use build_same_sized_truth_vector_type
>> >> instead of get_vectype_for_scalar_type in case statement produces a
>> >> boolean vector. This covers cases when we use invariants in
>> >> comparison, AND, IOR, XOR.
>> >
>> > Yes, I understand we need this special-casing to differentiate between
>> > the vector type
>> > used for boolean-typed loads/stores and the type for boolean typed constants.
>> > What happens if we mix them btw, like with
>> >
>> >   _Bool b = bools[i];
>> >   _Bool c = b || d;
>> >   ...
>> >
>> > ?
>>
>> Here both statements should get vector of char as a vectype and we
>> never go VECTOR_BOOLEAN_TYPE_P way for them
>>
>> >
>> >> 2. COND_EXPR is an exception because it has built-in boolean vector
>> >> result not reflected in its vecinfo. Thus I added additional operand
>> >> for vect_get_vec_def_for_operand to directly specify vectype for
>> >> vector definition in case it is a loop invariant.
>> >> So what do you propose to do with these changes?
>> >
>> > This is the change I don't like and don't see why we need it.  It works today
>> > and the comparison operands should be of appropriate type already?
>>
>> Today it works because we always create vector of integer constant.
>> With boolean vectors it may be either integer vector or boolean vector
>> depending on context. Consider:
>>
>> _Bool _1;
>> int _2;
>>
>> _2 = _1 != 0 ? 0 : 1
>>
>> We have two zero constants here requiring different vectypes.
>>
>> Ilya
>>
>> >
>> > Richard.
>> >
>> >> Thanks,
>> >> Ilya
>
> Here is an updated patch version.
>
> Thanks,
> Ilya
> --
> gcc/
>
> 2015-10-14  Ilya Enkovich  <enkovich.gnu@gmail.com>
>
>         * expr.c (const_vector_mask_from_tree): New.
>         (const_vector_from_tree): Use const_vector_mask_from_tree
>         for boolean vectors.
>         * tree-vect-stmts.c (vect_init_vector): Support boolean vector
>         invariants.
>         (vect_get_vec_def_for_operand): Add VECTYPE arg.
>         (vectorizable_condition): Directly provide vectype for invariants
>         used in comparison.
>         * tree-vectorizer.h (vect_get_vec_def_for_operand): Add VECTYPE
>         arg.
>
>
> diff --git a/gcc/expr.c b/gcc/expr.c
> index b5ff598..ab25d1a 100644
> --- a/gcc/expr.c
> +++ b/gcc/expr.c
> @@ -11344,6 +11344,40 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
>    return 1;
>  }
>
> +/* Return a CONST_VECTOR rtx representing vector mask for
> +   a VECTOR_CST of booleans.  */
> +static rtx
> +const_vector_mask_from_tree (tree exp)
> +{
> +  rtvec v;
> +  unsigned i;
> +  int units;
> +  tree elt;
> +  machine_mode inner, mode;
> +
> +  mode = TYPE_MODE (TREE_TYPE (exp));
> +  units = GET_MODE_NUNITS (mode);
> +  inner = GET_MODE_INNER (mode);
> +
> +  v = rtvec_alloc (units);
> +
> +  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
> +    {
> +      elt = VECTOR_CST_ELT (exp, i);
> +
> +      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
> +      if (integer_zerop (elt))
> +       RTVEC_ELT (v, i) = CONST0_RTX (inner);
> +      else if (integer_onep (elt)
> +              || integer_minus_onep (elt))
> +       RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
> +      else
> +       gcc_unreachable ();
> +    }
> +
> +  return gen_rtx_CONST_VECTOR (mode, v);
> +}
> +
>  /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
>  static rtx
>  const_vector_from_tree (tree exp)
> @@ -11359,6 +11393,9 @@ const_vector_from_tree (tree exp)
>    if (initializer_zerop (exp))
>      return CONST0_RTX (mode);
>
> +  if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
> +    return const_vector_mask_from_tree (exp);
> +
>    units = GET_MODE_NUNITS (mode);
>    inner = GET_MODE_INNER (mode);
>
> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
> index 6a52895..01168ae 100644
> --- a/gcc/tree-vect-stmts.c
> +++ b/gcc/tree-vect-stmts.c
> @@ -1308,7 +1308,22 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>        if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
>         {
>           if (CONSTANT_CLASS_P (val))
> -           val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
> +           {
> +             /* Can't use VIEW_CONVERT_EXPR for booleans because
> +                of possibly different sizes of scalar value and
> +                vector element.  */
> +             if (VECTOR_BOOLEAN_TYPE_P (type))
> +               {
> +                 if (integer_zerop (val))
> +                   val = build_int_cst (TREE_TYPE (type), 0);
> +                 else if (integer_onep (val))
> +                   val = build_int_cst (TREE_TYPE (type), 1);
> +                 else
> +                   gcc_unreachable ();
> +               }
> +             else
> +               val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);

I think the existing code is fine with using fold_convert () here
which should also work
for the boolean types.  So does just

                  val = fold_convert (TREE_TYPE (type), val);

work?

> +           }
>           else
>             {
>               new_temp = make_ssa_name (TREE_TYPE (type));
> @@ -1339,16 +1354,19 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>     STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
>
>     In case OP is an invariant or constant, a new stmt that creates a vector def
> -   needs to be introduced.  */
> +   needs to be introduced.  VECTYPE may be used to specify a required type for
> +   vector invariant.  */
>
>  tree
> -vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
> +vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def,
> +                             tree vectype)
>  {
>    tree vec_oprnd;
>    gimple *vec_stmt;
>    gimple *def_stmt;
>    stmt_vec_info def_stmt_info = NULL;
>    stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
> +  tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
>    unsigned int nunits;
>    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
>    tree def;
> @@ -1392,7 +1410,14 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>      /* Case 1: operand is a constant.  */
>      case vect_constant_def:
>        {
> -       vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
> +       if (vectype)
> +         vector_type = vectype;
> +       else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
> +                && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
> +         vector_type = build_same_sized_truth_vector_type (stmt_vectype);
> +       else
> +         vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
> +
>         gcc_assert (vector_type);
>         nunits = TYPE_VECTOR_SUBPARTS (vector_type);
>
> @@ -1410,7 +1435,13 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree *scalar_def)
>      /* Case 2: operand is defined outside the loop - loop invariant.  */
>      case vect_external_def:
>        {
> -       vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
> +       if (vectype)
> +         vector_type = vectype;
> +       else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
> +                && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
> +         vector_type = build_same_sized_truth_vector_type (stmt_vectype);
> +       else
> +         vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
>         gcc_assert (vector_type);
>
>         if (scalar_def)
> @@ -7428,13 +7459,13 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
>               gimple *gtemp;
>               vec_cond_lhs =
>               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
> -                                           stmt, NULL);
> +                                           stmt, NULL, comp_vectype);
>               vect_is_simple_use (TREE_OPERAND (cond_expr, 0), stmt,
>                                   loop_vinfo, &gtemp, &def, &dts[0]);
>
>               vec_cond_rhs =
>                 vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
> -                                               stmt, NULL);
> +                                             stmt, NULL, comp_vectype);
>               vect_is_simple_use (TREE_OPERAND (cond_expr, 1), stmt,
>                                   loop_vinfo, &gtemp, &def, &dts[1]);

I still don't like this very much but I guess without some major
refactoring of all
the functions there isn't a better way to do it for now.

Thus, ok with trying the change suggested above.

Thanks,
Richard.


>               if (reduc_index == 1)
> diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
> index f8d1e97..8eca7be 100644
> --- a/gcc/tree-vectorizer.h
> +++ b/gcc/tree-vectorizer.h
> @@ -994,7 +994,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
>  extern void vect_finish_stmt_generation (gimple *, gimple *,
>                                           gimple_stmt_iterator *);
>  extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
> -extern tree vect_get_vec_def_for_operand (tree, gimple *, tree *);
> +extern tree vect_get_vec_def_for_operand (tree, gimple *, tree *, tree = NULL);
>  extern tree vect_init_vector (gimple *, tree, tree,
>                                gimple_stmt_iterator *);
>  extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);

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

* Re: [vec-cmp, patch 4/6] Support vector mask invariants
  2015-10-26 15:25           ` Richard Biener
@ 2015-11-09 12:11             ` Ilya Enkovich
  2015-11-09 14:28               ` Richard Biener
  0 siblings, 1 reply; 9+ messages in thread
From: Ilya Enkovich @ 2015-11-09 12:11 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

On 26 Oct 16:21, Richard Biener wrote:
> On Wed, Oct 14, 2015 at 6:13 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
> > -           val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
> > +           {
> > +             /* Can't use VIEW_CONVERT_EXPR for booleans because
> > +                of possibly different sizes of scalar value and
> > +                vector element.  */
> > +             if (VECTOR_BOOLEAN_TYPE_P (type))
> > +               {
> > +                 if (integer_zerop (val))
> > +                   val = build_int_cst (TREE_TYPE (type), 0);
> > +                 else if (integer_onep (val))
> > +                   val = build_int_cst (TREE_TYPE (type), 1);
> > +                 else
> > +                   gcc_unreachable ();
> > +               }
> > +             else
> > +               val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
> 
> I think the existing code is fine with using fold_convert () here
> which should also work
> for the boolean types.  So does just
> 
>                   val = fold_convert (TREE_TYPE (type), val);
> 
> work?

It seems to work OK.

> 
> > @@ -7428,13 +7459,13 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
> >               gimple *gtemp;
> >               vec_cond_lhs =
> >               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
> > -                                           stmt, NULL);
> > +                                           stmt, NULL, comp_vectype);
> >               vect_is_simple_use (TREE_OPERAND (cond_expr, 0), stmt,
> >                                   loop_vinfo, &gtemp, &def, &dts[0]);
> >
> >               vec_cond_rhs =
> >                 vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
> > -                                               stmt, NULL);
> > +                                             stmt, NULL, comp_vectype);
> >               vect_is_simple_use (TREE_OPERAND (cond_expr, 1), stmt,
> >                                   loop_vinfo, &gtemp, &def, &dts[1]);
> 
> I still don't like this very much but I guess without some major
> refactoring of all
> the functions there isn't a better way to do it for now.
> 
> Thus, ok with trying the change suggested above.
> 
> Thanks,
> Richard.
> 

Here is an updated version.

Thanks,
Ilya
--
gcc/

2015-11-09  Ilya Enkovich  <enkovich.gnu@gmail.com>

	* expr.c (const_vector_mask_from_tree): New.
	(const_vector_from_tree): Use const_vector_mask_from_tree
	for boolean vectors.
	* tree-vect-stmts.c (vect_init_vector): Support boolean vector
	invariants.
	(vect_get_vec_def_for_operand): Add VECTYPE arg.
	(vectorizable_condition): Directly provide vectype for invariants
	used in comparison.
	* tree-vectorizer.h (vect_get_vec_def_for_operand): Add VECTYPE
	arg.


diff --git a/gcc/expr.c b/gcc/expr.c
index 2b2174f..03936ee 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11423,6 +11423,40 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
   return 1;
 }
 
+/* Return a CONST_VECTOR rtx representing vector mask for
+   a VECTOR_CST of booleans.  */
+static rtx
+const_vector_mask_from_tree (tree exp)
+{
+  rtvec v;
+  unsigned i;
+  int units;
+  tree elt;
+  machine_mode inner, mode;
+
+  mode = TYPE_MODE (TREE_TYPE (exp));
+  units = GET_MODE_NUNITS (mode);
+  inner = GET_MODE_INNER (mode);
+
+  v = rtvec_alloc (units);
+
+  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
+    {
+      elt = VECTOR_CST_ELT (exp, i);
+
+      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
+      if (integer_zerop (elt))
+	RTVEC_ELT (v, i) = CONST0_RTX (inner);
+      else if (integer_onep (elt)
+	       || integer_minus_onep (elt))
+	RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
+      else
+	gcc_unreachable ();
+    }
+
+  return gen_rtx_CONST_VECTOR (mode, v);
+}
+
 /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
 static rtx
 const_vector_from_tree (tree exp)
@@ -11438,6 +11472,9 @@ const_vector_from_tree (tree exp)
   if (initializer_zerop (exp))
     return CONST0_RTX (mode);
 
+  if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
+    return const_vector_mask_from_tree (exp);
+
   units = GET_MODE_NUNITS (mode);
   inner = GET_MODE_INNER (mode);
 
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index ee549f4..af203ab 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1300,7 +1300,7 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
       if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
 	{
 	  if (CONSTANT_CLASS_P (val))
-	    val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
+	    val = fold_convert (TREE_TYPE (type), val);
 	  else
 	    {
 	      new_temp = make_ssa_name (TREE_TYPE (type));
@@ -1328,16 +1328,18 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
    STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
 
    In case OP is an invariant or constant, a new stmt that creates a vector def
-   needs to be introduced.  */
+   needs to be introduced.  VECTYPE may be used to specify a required type for
+   vector invariant.  */
 
 tree
-vect_get_vec_def_for_operand (tree op, gimple *stmt)
+vect_get_vec_def_for_operand (tree op, gimple *stmt, tree vectype)
 {
   tree vec_oprnd;
   gimple *vec_stmt;
   gimple *def_stmt;
   stmt_vec_info def_stmt_info = NULL;
   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+  tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
   enum vect_def_type dt;
   bool is_simple_use;
@@ -1372,7 +1374,14 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt)
     case vect_constant_def:
     case vect_external_def:
       {
-	vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+	if (vectype)
+	  vector_type = vectype;
+	else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
+		 && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
+	  vector_type = build_same_sized_truth_vector_type (stmt_vectype);
+	else
+	  vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+
 	gcc_assert (vector_type);
         return vect_init_vector (stmt, op, vector_type, NULL);
       }
@@ -7329,13 +7338,14 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
             {
 	      gimple *gtemp;
 	      vec_cond_lhs =
-	      vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt);
+		vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
+					      stmt, comp_vectype);
 	      vect_is_simple_use (TREE_OPERAND (cond_expr, 0),
 				  loop_vinfo, &gtemp, &dts[0]);
 
 	      vec_cond_rhs =
 		vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
-					      stmt);
+					      stmt, comp_vectype);
 	      vect_is_simple_use (TREE_OPERAND (cond_expr, 1),
 				  loop_vinfo, &gtemp, &dts[1]);
 	      if (reduc_index == 1)
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 58d5f0b..d38d767 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -978,7 +978,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
 extern void vect_finish_stmt_generation (gimple *, gimple *,
                                          gimple_stmt_iterator *);
 extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
-extern tree vect_get_vec_def_for_operand (tree, gimple *);
+extern tree vect_get_vec_def_for_operand (tree, gimple *, tree = NULL);
 extern tree vect_init_vector (gimple *, tree, tree,
                               gimple_stmt_iterator *);
 extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);

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

* Re: [vec-cmp, patch 4/6] Support vector mask invariants
  2015-11-09 12:11             ` Ilya Enkovich
@ 2015-11-09 14:28               ` Richard Biener
  0 siblings, 0 replies; 9+ messages in thread
From: Richard Biener @ 2015-11-09 14:28 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: GCC Patches

On Mon, Nov 9, 2015 at 1:11 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
> On 26 Oct 16:21, Richard Biener wrote:
>> On Wed, Oct 14, 2015 at 6:13 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
>> > -           val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
>> > +           {
>> > +             /* Can't use VIEW_CONVERT_EXPR for booleans because
>> > +                of possibly different sizes of scalar value and
>> > +                vector element.  */
>> > +             if (VECTOR_BOOLEAN_TYPE_P (type))
>> > +               {
>> > +                 if (integer_zerop (val))
>> > +                   val = build_int_cst (TREE_TYPE (type), 0);
>> > +                 else if (integer_onep (val))
>> > +                   val = build_int_cst (TREE_TYPE (type), 1);
>> > +                 else
>> > +                   gcc_unreachable ();
>> > +               }
>> > +             else
>> > +               val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
>>
>> I think the existing code is fine with using fold_convert () here
>> which should also work
>> for the boolean types.  So does just
>>
>>                   val = fold_convert (TREE_TYPE (type), val);
>>
>> work?
>
> It seems to work OK.
>
>>
>> > @@ -7428,13 +7459,13 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
>> >               gimple *gtemp;
>> >               vec_cond_lhs =
>> >               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
>> > -                                           stmt, NULL);
>> > +                                           stmt, NULL, comp_vectype);
>> >               vect_is_simple_use (TREE_OPERAND (cond_expr, 0), stmt,
>> >                                   loop_vinfo, &gtemp, &def, &dts[0]);
>> >
>> >               vec_cond_rhs =
>> >                 vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
>> > -                                               stmt, NULL);
>> > +                                             stmt, NULL, comp_vectype);
>> >               vect_is_simple_use (TREE_OPERAND (cond_expr, 1), stmt,
>> >                                   loop_vinfo, &gtemp, &def, &dts[1]);
>>
>> I still don't like this very much but I guess without some major
>> refactoring of all
>> the functions there isn't a better way to do it for now.
>>
>> Thus, ok with trying the change suggested above.
>>
>> Thanks,
>> Richard.
>>
>
> Here is an updated version.

Ok.

Thanks,
Richard.

> Thanks,
> Ilya
> --
> gcc/
>
> 2015-11-09  Ilya Enkovich  <enkovich.gnu@gmail.com>
>
>         * expr.c (const_vector_mask_from_tree): New.
>         (const_vector_from_tree): Use const_vector_mask_from_tree
>         for boolean vectors.
>         * tree-vect-stmts.c (vect_init_vector): Support boolean vector
>         invariants.
>         (vect_get_vec_def_for_operand): Add VECTYPE arg.
>         (vectorizable_condition): Directly provide vectype for invariants
>         used in comparison.
>         * tree-vectorizer.h (vect_get_vec_def_for_operand): Add VECTYPE
>         arg.
>
>
> diff --git a/gcc/expr.c b/gcc/expr.c
> index 2b2174f..03936ee 100644
> --- a/gcc/expr.c
> +++ b/gcc/expr.c
> @@ -11423,6 +11423,40 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
>    return 1;
>  }
>
> +/* Return a CONST_VECTOR rtx representing vector mask for
> +   a VECTOR_CST of booleans.  */
> +static rtx
> +const_vector_mask_from_tree (tree exp)
> +{
> +  rtvec v;
> +  unsigned i;
> +  int units;
> +  tree elt;
> +  machine_mode inner, mode;
> +
> +  mode = TYPE_MODE (TREE_TYPE (exp));
> +  units = GET_MODE_NUNITS (mode);
> +  inner = GET_MODE_INNER (mode);
> +
> +  v = rtvec_alloc (units);
> +
> +  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
> +    {
> +      elt = VECTOR_CST_ELT (exp, i);
> +
> +      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
> +      if (integer_zerop (elt))
> +       RTVEC_ELT (v, i) = CONST0_RTX (inner);
> +      else if (integer_onep (elt)
> +              || integer_minus_onep (elt))
> +       RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
> +      else
> +       gcc_unreachable ();
> +    }
> +
> +  return gen_rtx_CONST_VECTOR (mode, v);
> +}
> +
>  /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
>  static rtx
>  const_vector_from_tree (tree exp)
> @@ -11438,6 +11472,9 @@ const_vector_from_tree (tree exp)
>    if (initializer_zerop (exp))
>      return CONST0_RTX (mode);
>
> +  if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
> +    return const_vector_mask_from_tree (exp);
> +
>    units = GET_MODE_NUNITS (mode);
>    inner = GET_MODE_INNER (mode);
>
> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
> index ee549f4..af203ab 100644
> --- a/gcc/tree-vect-stmts.c
> +++ b/gcc/tree-vect-stmts.c
> @@ -1300,7 +1300,7 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>        if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
>         {
>           if (CONSTANT_CLASS_P (val))
> -           val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
> +           val = fold_convert (TREE_TYPE (type), val);
>           else
>             {
>               new_temp = make_ssa_name (TREE_TYPE (type));
> @@ -1328,16 +1328,18 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
>     STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
>
>     In case OP is an invariant or constant, a new stmt that creates a vector def
> -   needs to be introduced.  */
> +   needs to be introduced.  VECTYPE may be used to specify a required type for
> +   vector invariant.  */
>
>  tree
> -vect_get_vec_def_for_operand (tree op, gimple *stmt)
> +vect_get_vec_def_for_operand (tree op, gimple *stmt, tree vectype)
>  {
>    tree vec_oprnd;
>    gimple *vec_stmt;
>    gimple *def_stmt;
>    stmt_vec_info def_stmt_info = NULL;
>    stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
> +  tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
>    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
>    enum vect_def_type dt;
>    bool is_simple_use;
> @@ -1372,7 +1374,14 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt)
>      case vect_constant_def:
>      case vect_external_def:
>        {
> -       vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
> +       if (vectype)
> +         vector_type = vectype;
> +       else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
> +                && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
> +         vector_type = build_same_sized_truth_vector_type (stmt_vectype);
> +       else
> +         vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
> +
>         gcc_assert (vector_type);
>          return vect_init_vector (stmt, op, vector_type, NULL);
>        }
> @@ -7329,13 +7338,14 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
>              {
>               gimple *gtemp;
>               vec_cond_lhs =
> -             vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt);
> +               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
> +                                             stmt, comp_vectype);
>               vect_is_simple_use (TREE_OPERAND (cond_expr, 0),
>                                   loop_vinfo, &gtemp, &dts[0]);
>
>               vec_cond_rhs =
>                 vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
> -                                             stmt);
> +                                             stmt, comp_vectype);
>               vect_is_simple_use (TREE_OPERAND (cond_expr, 1),
>                                   loop_vinfo, &gtemp, &dts[1]);
>               if (reduc_index == 1)
> diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
> index 58d5f0b..d38d767 100644
> --- a/gcc/tree-vectorizer.h
> +++ b/gcc/tree-vectorizer.h
> @@ -978,7 +978,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
>  extern void vect_finish_stmt_generation (gimple *, gimple *,
>                                           gimple_stmt_iterator *);
>  extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
> -extern tree vect_get_vec_def_for_operand (tree, gimple *);
> +extern tree vect_get_vec_def_for_operand (tree, gimple *, tree = NULL);
>  extern tree vect_init_vector (gimple *, tree, tree,
>                                gimple_stmt_iterator *);
>  extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);

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

end of thread, other threads:[~2015-11-09 14:28 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-08 15:12 [vec-cmp, patch 4/6] Support vector mask invariants Ilya Enkovich
2015-10-13 13:54 ` Richard Biener
2015-10-13 14:52   ` Ilya Enkovich
2015-10-14  8:49     ` Richard Biener
2015-10-14 10:50       ` Ilya Enkovich
2015-10-14 16:14         ` Ilya Enkovich
2015-10-26 15:25           ` Richard Biener
2015-11-09 12:11             ` Ilya Enkovich
2015-11-09 14:28               ` 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).