[vec-cmp, patch 4/6] Support vector mask invariants
Richard Biener
richard.guenther@gmail.com
Wed Oct 14 08:49:00 GMT 2015
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, >emp, &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, >emp, &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
More information about the Gcc-patches
mailing list