Message ID | 20220211123517.ED01E13C6D@imap2.suse-dmz.suse.de |
---|---|
State | New |
Headers | show |
Series | [gimplefe] Add vector_mask attribute to get access to vector bools | expand |
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; > +}
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; +}