@@ -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,
@@ -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 }
@@ -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:
new file mode 100644
@@ -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} } } */