Richard Biener <rguent...@suse.de> writes:
> The following adds __attribute__((vector_mask)) to get access to
> the corresponding mask type for a vector type.  The implementation
> simply uses truth_type_for so creating a mask type that's not
> what the target would choose as canonical, say a AVX2 style one
> when AVX512VL is enabled, is not possible.  It might be possible
> to provide access to that with an optional argument specifying
> the precision of the bool element.  The syntax is as simple as
>
> typedef vector_type mask_type __attribute__((vector_mask));
>
> In theory this allows to create unit testcases for vector
> lowering and ISEL.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, I've also
> checked that it works with SVE and -msve-vector-bits=256 but
> I'm unsure how to build the vector type for a variable size case.
> Without -msve-vector-bits=256 the testcase is decomposed by
> vector lowering (I suppose there's no good way to "decompose"
> a fixed width vector to a variable length one without creating
> a loop around each stmt...).
>
> OK?

LGTM.  As mentioned on IRC, it also seems to work for the
variable-length case.  E.g. (names now meaningless):

typedef __SVInt8_t v8si;
typedef v8si v8sib __attribute__((vector_mask));

v8si __GIMPLE (ssa) foo (v8si v1, v8si v2, v8si v3, v8si v4)
{
  v8sib tem;
  v8si resr;

__BB(2):
  tem_3 = v1_1(D) <= v2_2(D);
  resr_4 = tem_3 ? v3_5(D) : v4_6(D);
  return resr_4;
}

produces:

        ptrue   p0.b, all
        cmple   p0.b, p0/z, z0.b, z1.b
        sel     z0.b, p0, z2.b, z3.b
        ret

Thanks,
Richard

>
> Thanks,
> Richard.
>
> 2022-02-11  Richard Biener  <rguent...@suse.de>
>
> gcc/c-family/
>       * c-attribs.cc (c_common_attribute_table): Add entry for
>       vector_mask.
>       (handle_vector_mask_attribute): New.
>
> gcc/c/
>       * gimple-fe.cc (c_parser_gimple_statement): Properly parse
>       VEC_COND_EXPRs.
>
> gcc/testsuite/
>       * gcc.dg/gimplefe-48.c: New testcase.
> ---
>  gcc/c-family/c-attribs.cc          | 36 ++++++++++++++++++++++++++++++
>  gcc/c/gimple-parser.cc             | 12 ++++++----
>  gcc/testsuite/gcc.dg/gimplefe-48.c | 19 ++++++++++++++++
>  3 files changed, 63 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/gimplefe-48.c
>
> diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
> index 4fb5dbd1409..3849dba90b2 100644
> --- a/gcc/c-family/c-attribs.cc
> +++ b/gcc/c-family/c-attribs.cc
> @@ -129,6 +129,8 @@ static tree handle_unavailable_attribute (tree *, tree, 
> tree, int,
>                                         bool *);
>  static tree handle_vector_size_attribute (tree *, tree, tree, int,
>                                         bool *) ATTRIBUTE_NONNULL(3);
> +static tree handle_vector_mask_attribute (tree *, tree, tree, int,
> +                                       bool *) ATTRIBUTE_NONNULL(3);
>  static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
>  static tree handle_nonstring_attribute (tree *, tree, tree, int, bool *);
>  static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
> @@ -417,6 +419,8 @@ const struct attribute_spec c_common_attribute_table[] =
>                             handle_unavailable_attribute, NULL },
>    { "vector_size",         1, 1, false, true, false, true,
>                             handle_vector_size_attribute, NULL },
> +  { "vector_mask",         0, 0, false, true, false, true,
> +                           handle_vector_mask_attribute, NULL },
>    { "visibility",          1, 1, false, false, false, false,
>                             handle_visibility_attribute, NULL },
>    { "tls_model",           1, 1, true,  false, false, false,
> @@ -4419,6 +4423,38 @@ handle_vector_size_attribute (tree *node, tree name, 
> tree args,
>    return NULL_TREE;
>  }
>  
> +/* Handle a "vector_mask" attribute; arguments as in
> +   struct attribute_spec.handler.  */
> +
> +static tree
> +handle_vector_mask_attribute (tree *node, tree name, tree,
> +                           int ARG_UNUSED (flags),
> +                           bool *no_add_attrs)
> +{
> +  *no_add_attrs = true;
> +  if (!flag_gimple)
> +    {
> +      warning (OPT_Wattributes, "%qE attribute ignored", name);
> +      return NULL_TREE;
> +    }
> +
> +  /* Determine the "base" type to apply the attribute to.  */
> +  tree type = type_for_vector_size (*node);
> +  if (!VECTOR_TYPE_P (type) || VECTOR_BOOLEAN_TYPE_P (type))
> +    {
> +      warning (OPT_Wattributes, "%qE attribute only supported on "
> +            "non-mask vector types", name);
> +      return NULL_TREE;
> +    }
> +
> +  tree new_type = truth_type_for (type);
> +
> +  /* Build back pointers if needed.  */
> +  *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
> +
> +  return NULL_TREE;
> +}
> +
>  /* Handle the "nonnull" attribute.  */
>  
>  static tree
> diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc
> index 51ddd86f23a..31075237c98 100644
> --- a/gcc/c/gimple-parser.cc
> +++ b/gcc/c/gimple-parser.cc
> @@ -860,9 +860,10 @@ c_parser_gimple_statement (gimple_parser &parser, 
> gimple_seq *seq)
>    if (lhs.value != error_mark_node
>        && rhs.value != error_mark_node)
>      {
> -      /* If we parsed a comparison and the next token is a '?' then
> -         parse a conditional expression.  */
> -      if (COMPARISON_CLASS_P (rhs.value)
> +      /* If we parsed a comparison or an identifier and the next token
> +      is a '?' then parse a conditional expression.  */
> +      if ((COMPARISON_CLASS_P (rhs.value)
> +        || SSA_VAR_P (rhs.value))
>         && c_parser_next_token_is (parser, CPP_QUERY))
>       {
>         struct c_expr trueval, falseval;
> @@ -874,7 +875,10 @@ c_parser_gimple_statement (gimple_parser &parser, 
> gimple_seq *seq)
>         if (trueval.value == error_mark_node
>             || falseval.value == error_mark_node)
>           return;
> -       rhs.value = build3_loc (loc, COND_EXPR, TREE_TYPE (trueval.value),
> +       rhs.value = build3_loc (loc,
> +                               VECTOR_TYPE_P (TREE_TYPE (rhs.value))
> +                               ? VEC_COND_EXPR : COND_EXPR,
> +                               TREE_TYPE (trueval.value),
>                                 rhs.value, trueval.value, falseval.value);
>       }
>        if (get_gimple_rhs_class (TREE_CODE (rhs.value)) == GIMPLE_INVALID_RHS)
> diff --git a/gcc/testsuite/gcc.dg/gimplefe-48.c 
> b/gcc/testsuite/gcc.dg/gimplefe-48.c
> new file mode 100644
> index 00000000000..13d534a40c1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gimplefe-48.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O -fgimple" } */
> +
> +typedef int v8si __attribute__((vector_size(8*sizeof(int))));
> +typedef v8si v8sib __attribute__((vector_mask));
> +
> +v8si res;
> +
> +void __GIMPLE (ssa) foo (v8si v1, v8si v2, v8si v3, v8si v4)
> +{
> +  v8sib tem;
> +  v8si resr;
> +
> +__BB(2):
> +  tem_3 = v1_1(D) <= v2_2(D);
> +  resr_4 = tem_3 ? v3_5(D) : v4_6(D);
> +  res = resr_4;
> +  return;
> +}

Reply via email to