2015-10-13 16:54 GMT+03:00 Richard Biener <richard.guent...@gmail.com>:
> On Thu, Oct 8, 2015 at 5:11 PM, Ilya Enkovich <enkovich....@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....@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

Reply via email to