This is a release branch version of r11-1741-g:31427b974ed7b7dd54e2. The trunk version 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. This code will be reused for AArch32 too. 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 test passes for unmodified sources even without the patch (unless you're very unlucky). Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK for branches? 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. 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. --- gcc/config/aarch64/aarch64-builtins.c | 14 +++++++---- gcc/config/aarch64/aarch64.c | 1 + gcc/cp/typeck.c | 9 +++++++ gcc/testsuite/g++.target/aarch64/pr95726.C | 28 ++++++++++++++++++++++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.target/aarch64/pr95726.C 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 8aeb78a4793..60173b34b23 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/cp/typeck.c b/gcc/cp/typeck.c index 5f8f8290f0f..34a27fe2414 100644 --- 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; + 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/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} } } */