[gimplefe] Add vector_mask attribute to get access to vector bools

Message ID 20220211123517.ED01E13C6D@imap2.suse-dmz.suse.de
State New
Headers
Series [gimplefe] Add vector_mask attribute to get access to vector bools |

Commit Message

Richard Biener Feb. 11, 2022, 12:35 p.m. UTC
  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?

Thanks,
Richard.

2022-02-11  Richard Biener  <rguenther@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
  

Comments

Richard Sandiford Feb. 11, 2022, 12:45 p.m. UTC | #1
Richard Biener <rguenther@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  <rguenther@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;
> +}
  

Patch

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;
+}