On Tue, Jul 14, 2020 at 1:21 AM Richard Sandiford <richard.sandif...@arm.com> wrote: > > Jakub Jelinek <ja...@redhat.com> writes: > > On Wed, Jul 08, 2020 at 03:10:14PM +0100, Richard Sandiford wrote: > >> gcc/ > >> PR target/95726 > >> * config/aarch64/aarch64.c (aarch64_attribute_table): Add > >> "Advanced SIMD type". > >> * config/aarch64/aarch64-builtins.c: Include stringpool.h and > >> attribs.h. > >> (aarch64_init_simd_builtin_types): Add an "Advanced SIMD type" > >> attribute to each Advanced SIMD type. > >> > >> gcc/cp/ > >> PR target/95726 > >> * typeck.c (structural_comptypes): When comparing template > >> specializations, differentiate between vectors that have and > >> do not have an "Advanced SIMD type" attribute. > >> > >> gcc/testsuite/ > >> PR target/95726 > >> * g++.target/aarch64/pr95726.C: New test. > >> --- a/gcc/cp/typeck.c > >> +++ b/gcc/cp/typeck.c > >> @@ -1429,6 +1429,15 @@ structural_comptypes (tree t1, tree t2, int strict) > >> || maybe_ne (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2)) > >> || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) > >> return false; > > > > I'd at least add an explaining comment that it is a hack for GCC 8-10 only, > > for aarch64 and arm targets, why, reference to the PR and that it is solved > > differently for GCC 11+. > > OK, done below. This version also includes arm support. > > >> + if (comparing_specializations) > >> + { > >> + bool asimd1 = lookup_attribute ("Advanced SIMD type", > >> + TYPE_ATTRIBUTES (t1)); > >> + bool asimd2 = lookup_attribute ("Advanced SIMD type", > >> + TYPE_ATTRIBUTES (t2)); > >> + if (asimd1 != asimd2) > >> + return false; > >> + } > > > > Otherwise LGTM for release branches if it is acceptable that way to Jason. > > Thanks. Jason, does it look OK from your point of view? > > Richard > > > This is a release branch version of > r11-1741-g:31427b974ed7b7dd54e28fec595e731bf6eea8ba and > r11-2022-g:efe99cca78215e339ba79f0a900a896b4c0a3d36. > > The trunk versions of the patch made GNU and Advanced SIMD vectors > distinct (but inter-convertible) in all cases. However, the > traditional behaviour is that the types are distinct in template > arguments but not otherwise. > > Following a suggestion from Jason, this patch puts the check > for different vector types under comparing_specializations. > In order to keep the backport as simple as possible, the patch > hard-codes the name of the attribute in the frontend rather than > adding a new branch-only target hook. > > I didn't find a test that tripped the assert on the branch, > even with the --param in the PR, so instead I tested this by > forcing the hash function to only hash the tree code. That made > the static assertion in the test fail without the patch but pass > with it. > > This means that the tests pass for unmodified sources even > without the patch (unless you're very unlucky).
Can you please apply this patch so I can roll GCC 10.2 RC1? In the unlikely event Jason requests changes we can integrate those early next week. Thanks, Richard. > gcc/ > PR target/95726 > * config/aarch64/aarch64.c (aarch64_attribute_table): Add > "Advanced SIMD type". > * config/aarch64/aarch64-builtins.c: Include stringpool.h and > attribs.h. > (aarch64_init_simd_builtin_types): Add an "Advanced SIMD type" > attribute to each Advanced SIMD type. > * config/arm/arm.c (arm_attribute_table): Add "Advanced SIMD type". > * config/arm/arm-builtins.c: Include stringpool.h and attribs.h. > (arm_init_simd_builtin_types): Add an "Advanced SIMD type" > attribute to each Advanced SIMD type. > > gcc/cp/ > PR target/95726 > * typeck.c (structural_comptypes): When comparing template > specializations, differentiate between vectors that have and > do not have an "Advanced SIMD type" attribute. > > gcc/testsuite/ > PR target/95726 > * g++.target/aarch64/pr95726.C: New test. > * g++.target/arm/pr95726.C: Likewise. > --- > gcc/config/aarch64/aarch64-builtins.c | 14 +++++--- > gcc/config/aarch64/aarch64.c | 1 + > gcc/config/arm/arm-builtins.c | 15 ++++++-- > gcc/config/arm/arm.c | 1 + > gcc/cp/typeck.c | 42 ++++++++++++++++++++++ > gcc/testsuite/g++.target/aarch64/pr95726.C | 28 +++++++++++++++ > gcc/testsuite/g++.target/arm/pr95726.C | 31 ++++++++++++++++ > 7 files changed, 125 insertions(+), 7 deletions(-) > create mode 100644 gcc/testsuite/g++.target/aarch64/pr95726.C > create mode 100644 gcc/testsuite/g++.target/arm/pr95726.C > > diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c > index 5f8f8290f0f..6ebf6319efd 100644 > --- a/gcc/cp/typeck.c > +++ b/gcc/cp/typeck.c > @@ -1429,6 +1429,48 @@ structural_comptypes (tree t1, tree t2, int strict) > || maybe_ne (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2)) > || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) > return false; > + > + /* This hack is specific to release branches and fixes PR95726 for > + arm and aarch64 targets. The idea is to treat GNU and Advanced > + SIMD types as distinct types for template specialization, but to > + treat them as the same type for other purposes. For example: > + > + typedef float vecf __attribute__((vector_size(16))); > + template<typename T> struct bar; > + template<> struct bar<vecf> { static const int x = 1; }; > + template<> struct bar<float32x4_t> { static const int x = 2; }; > + static_assert(bar<vecf>::x + bar<float32x4_t>::x == 3, "boo"); > + > + is supposed to be valid, and so "vecf" and "float32x4_t" should > + be different for at least template specialization. However, > + GCC 10 and earlier also allowed things like: > + > + vecf x; > + float32x4_t &z = x; > + > + and: > + > + vecf x; > + float32x4_t y; > + ... c ? x : y ... > + > + both of which require "vecf" and "float32x4_t" to be the same. > + > + This was fixed in GCC 11+ by making the types distinct in all > + contexts, making the reference binding and ?: expression above > + invalid. However, it would be inappropriate to change the > + semantics like that in release branches, so we do this instead. > + The space in the attribute name prevents any clash with user- > + specified attributes. */ > + if (comparing_specializations) > + { > + bool asimd1 = lookup_attribute ("Advanced SIMD type", > + TYPE_ATTRIBUTES (t1)); > + bool asimd2 = lookup_attribute ("Advanced SIMD type", > + TYPE_ATTRIBUTES (t2)); > + if (asimd1 != asimd2) > + return false; > + } > break; > > case TYPE_PACK_EXPANSION: > diff --git a/gcc/config/aarch64/aarch64-builtins.c > b/gcc/config/aarch64/aarch64-builtins.c > index 95213cd70c8..8407a34b594 100644 > --- a/gcc/config/aarch64/aarch64-builtins.c > +++ b/gcc/config/aarch64/aarch64-builtins.c > @@ -43,6 +43,8 @@ > #include "gimple-iterator.h" > #include "case-cfn-macros.h" > #include "emit-rtl.h" > +#include "stringpool.h" > +#include "attribs.h" > > #define v8qi_UP E_V8QImode > #define v4hi_UP E_V4HImode > @@ -802,10 +804,14 @@ aarch64_init_simd_builtin_types (void) > > if (aarch64_simd_types[i].itype == NULL) > { > - aarch64_simd_types[i].itype > - = build_distinct_type_copy > - (build_vector_type (eltype, GET_MODE_NUNITS (mode))); > - SET_TYPE_STRUCTURAL_EQUALITY (aarch64_simd_types[i].itype); > + tree type = build_vector_type (eltype, GET_MODE_NUNITS (mode)); > + type = build_distinct_type_copy (type); > + SET_TYPE_STRUCTURAL_EQUALITY (type); > + > + TYPE_ATTRIBUTES (type) > + = tree_cons (get_identifier ("Advanced SIMD type"), > + NULL_TREE, TYPE_ATTRIBUTES (type)); > + aarch64_simd_types[i].itype = type; > } > > tdecl = add_builtin_type (aarch64_simd_types[i].name, > diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c > index cda494c4bbf..cd67dcfba37 100644 > --- a/gcc/config/aarch64/aarch64.c > +++ b/gcc/config/aarch64/aarch64.c > @@ -1429,6 +1429,7 @@ static const struct attribute_spec > aarch64_attribute_table[] = > { "arm_sve_vector_bits", 1, 1, false, true, false, true, > aarch64_sve::handle_arm_sve_vector_bits_attribute, > NULL }, > + { "Advanced SIMD type", 0, 0, false, true, false, true, NULL, NULL }, > { "SVE type", 3, 3, false, true, false, true, NULL, > NULL }, > { "SVE sizeless type", 0, 0, false, true, false, true, NULL, NULL }, > { NULL, 0, 0, false, false, false, false, NULL, NULL } > diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c > index f64742e6447..658dacfb5bf 100644 > --- a/gcc/config/arm/arm-builtins.c > +++ b/gcc/config/arm/arm-builtins.c > @@ -43,6 +43,8 @@ > #include "sbitmap.h" > #include "stringpool.h" > #include "arm-builtins.h" > +#include "stringpool.h" > +#include "attribs.h" > > #define SIMD_MAX_BUILTIN_ARGS 7 > > @@ -1642,9 +1644,16 @@ arm_init_simd_builtin_types (void) > if (eltype == NULL) > continue; > if (arm_simd_types[i].itype == NULL) > - arm_simd_types[i].itype = > - build_distinct_type_copy > - (build_vector_type (eltype, GET_MODE_NUNITS (mode))); > + { > + tree type = build_vector_type (eltype, GET_MODE_NUNITS (mode)); > + type = build_distinct_type_copy (type); > + SET_TYPE_STRUCTURAL_EQUALITY (type); > + > + TYPE_ATTRIBUTES (type) > + = tree_cons (get_identifier ("Advanced SIMD type"), > + NULL_TREE, TYPE_ATTRIBUTES (type)); > + arm_simd_types[i].itype = type; > + } > > tdecl = add_builtin_type (arm_simd_types[i].name, > arm_simd_types[i].itype); > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > index 3f12dbfbfc9..a8825ee3ee4 100644 > --- a/gcc/config/arm/arm.c > +++ b/gcc/config/arm/arm.c > @@ -382,6 +382,7 @@ static const struct attribute_spec arm_attribute_table[] = > arm_handle_cmse_nonsecure_entry, NULL }, > { "cmse_nonsecure_call", 0, 0, true, false, false, true, > arm_handle_cmse_nonsecure_call, NULL }, > + { "Advanced SIMD type", 0, 0, false, true, false, true, NULL, NULL }, > { NULL, 0, 0, false, false, false, false, NULL, NULL } > }; > > diff --git a/gcc/testsuite/g++.target/aarch64/pr95726.C > b/gcc/testsuite/g++.target/aarch64/pr95726.C > new file mode 100644 > index 00000000000..3327b335ff5 > --- /dev/null > +++ b/gcc/testsuite/g++.target/aarch64/pr95726.C > @@ -0,0 +1,28 @@ > +#include <arm_neon.h> > + > +typedef float vecf __attribute__((vector_size(16))); > + > +// This assertion must hold: vecf and float32x4_t have distinct identities > +// and mangle differently, so they are not interchangeable. > +template<typename T> struct bar; > +template<> struct bar<vecf> { static const int x = 1; }; > +template<> struct bar<float32x4_t> { static const int x = 2; }; > +static_assert(bar<vecf>::x + bar<float32x4_t>::x == 3, "boo"); > + > +// GCC 10 and earlier should continue to accept this, but the behavior > +// changed in GCC 11. > +vecf x; > +float32x4_t y; > +float32x4_t &z = x; > + > +// These assignment must be valid even in the strictest mode: vecf must > +// implicitly convert to float32x4_t and vice versa. > +void foo() { x = y; y = x; } > + > +// GCC 10 and earlier should continue to accept this, but the behavior > +// changed in GCC 11. > +auto sel1(bool c, decltype(c ? x : y) d) { return d; } > +auto sel2(bool c, decltype(c ? y : x) d) { return d; } > + > +/* { dg-final { scan-assembler {_Z4sel1bRDv4_f} } } */ > +/* { dg-final { scan-assembler {_Z4sel2bR13__Float32x4_t} } } */ > diff --git a/gcc/testsuite/g++.target/arm/pr95726.C > b/gcc/testsuite/g++.target/arm/pr95726.C > new file mode 100644 > index 00000000000..1db15e1030b > --- /dev/null > +++ b/gcc/testsuite/g++.target/arm/pr95726.C > @@ -0,0 +1,31 @@ > +// { dg-require-effective-target arm_neon_ok } > +// { dg-add-options arm_neon } > + > +#include <arm_neon.h> > + > +typedef float vecf __attribute__((vector_size(16))); > + > +// This assertion must hold: vecf and float32x4_t have distinct identities > +// and mangle differently, so they are not interchangeable. > +template<typename T> struct bar; > +template<> struct bar<vecf> { static const int x = 1; }; > +template<> struct bar<float32x4_t> { static const int x = 2; }; > +static_assert(bar<vecf>::x + bar<float32x4_t>::x == 3, "boo"); > + > +// GCC 10 and earlier should continue to accept this, but the behavior > +// changed in GCC 11. > +vecf x; > +float32x4_t y; > +float32x4_t &z = x; > + > +// These assignment must be valid even in the strictest mode: vecf must > +// implicitly convert to float32x4_t and vice versa. > +void foo() { x = y; y = x; } > + > +// GCC 10 and earlier should continue to accept this, but the behavior > +// changed in GCC 11. > +auto sel1(bool c, decltype(c ? x : y) d) { return d; } > +auto sel2(bool c, decltype(c ? y : x) d) { return d; } > + > +/* { dg-final { scan-assembler {_Z4sel1bRDv4_f} } } */ > +/* { dg-final { scan-assembler {_Z4sel2bR19__simd128_float32_t} } } */