public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
@ 2019-12-18 16:40 Stam Markianos-Wright
  2019-12-19 10:10 ` Richard Sandiford
  0 siblings, 1 reply; 10+ messages in thread
From: Stam Markianos-Wright @ 2019-12-18 16:40 UTC (permalink / raw)
  To: gcc-patches
  Cc: Richard Earnshaw, Richard Sandiford, Kyrylo Tkachov, Marcus Shawcroft

[-- Attachment #1: Type: text/plain, Size: 1526 bytes --]

Hi all,

This patch is part 2 of Bfloat16_t enablement in the Aarch64 back-end.

This new type is constrained using target hooks TARGET_INVALID_CONVERSION, 
TARGET_INVALID_UNARY_OP, TARGET_INVALID_BINARY_OP so that it may only be used 
through ACLE intrinsics (will be provided in later patches).

Regression testing on aarch64-none-elf passed successfully.

Ok for trunk?

Cheers,
Stam


ACLE documents are at https://developer.arm.com/docs/101028/latest
ISA documents are at https://developer.arm.com/docs/ddi0596/latest

Details on ARM Bfloat can be found here:
https://community.arm.com/developer/ip-products/processors/b/ml-ip-blog/posts/bfloat16-processing-for-neural-networks-on-armv8_2d00_a 


PS. I don't have commit rights, so if someone could commit on my behalf,
that would be great :)


gcc/ChangeLog:

2019-12-16  Stam Markianos-Wright  <stam.markianos-wright@arm.com>

	* config/aarch64/aarch64.c
	(aarch64_invalid_conversion): New function for target hook.
	(aarch64_invalid_unary_op): Likewise.
	(aarch64_invalid_binary_op): Likewise.
	(TARGET_INVALID_CONVERSION): Add back-end define for target hook.
	(TARGET_INVALID_UNARY_OP): Likewise.
	(TARGET_INVALID_BINARY_OP): Likewise.


gcc/testsuite/ChangeLog:

2019-12-16  Stam Markianos-Wright  <stam.markianos-wright@arm.com>

	* gcc.target/aarch64/bfloat16_scalar_typecheck.c: New test.
	* gcc.target/aarch64/bfloat16_vector_typecheck1.c: New test.
	* gcc.target/aarch64/bfloat16_vector_typecheck2.c: New test.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: BFmode2of2.patch --]
[-- Type: text/x-patch; name="BFmode2of2.patch", Size: 14386 bytes --]

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index f57469b6e23..f40f6432fd4 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -21661,6 +21661,68 @@ aarch64_stack_protect_guard (void)
   return NULL_TREE;
 }
 
+/* Return the diagnostic message string if conversion from FROMTYPE to
+   TOTYPE is not allowed, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
+{
+  static char templ[100];
+  if ((GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode
+       || GET_MODE_INNER (TYPE_MODE (totype)) == BFmode)
+       && TYPE_MODE (fromtype) != TYPE_MODE (totype))
+  {
+    snprintf (templ, sizeof (templ), \
+      "incompatible types when assigning to type '%s' from type '%s'",
+      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (totype))),
+      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (fromtype))));
+    return N_(templ);
+  }
+  /* Conversion allowed.  */
+  return NULL;
+}
+
+/* Return the diagnostic message string if the unary operation OP is
+   not permitted on TYPE, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_unary_op (int op, const_tree type)
+{
+  static char templ[100];
+  /* Reject all single-operand operations on BFmode except for &.  */
+  if (GET_MODE_INNER (TYPE_MODE (type)) == BFmode && op != ADDR_EXPR)
+  {
+    snprintf (templ, sizeof (templ),
+      "operation not permitted on type '%s'",
+      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+    return N_(templ);
+  }
+  /* Operation allowed.  */
+  return NULL;
+}
+
+/* Return the diagnostic message string if the binary operation OP is
+   not permitted on TYPE1 and TYPE2, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
+			   const_tree type2)
+{
+  static char templ[100];
+  /* Reject all 2-operand operations on BFmode.  */
+  if (GET_MODE_INNER (TYPE_MODE (type1)) == BFmode
+      || GET_MODE_INNER (TYPE_MODE (type2)) == BFmode)
+  {
+    snprintf (templ, sizeof (templ), \
+      "operation not permitted on types '%s', '%s'",
+      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type1))),
+      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2))));
+    return N_(templ);
+  }
+  /* Operation allowed.  */
+  return NULL;
+}
+
 /* Implement TARGET_ASM_FILE_END for AArch64.  This adds the AArch64 GNU NOTE
    section at the end if needed.  */
 #define GNU_PROPERTY_AARCH64_FEATURE_1_AND	0xc0000000
@@ -21911,6 +21973,15 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE aarch64_mangle_type
 
+#undef TARGET_INVALID_CONVERSION
+#define TARGET_INVALID_CONVERSION aarch64_invalid_conversion
+
+#undef TARGET_INVALID_UNARY_OP
+#define TARGET_INVALID_UNARY_OP aarch64_invalid_unary_op
+
+#undef TARGET_INVALID_BINARY_OP
+#define TARGET_INVALID_BINARY_OP aarch64_invalid_binary_op
+
 #undef TARGET_VERIFY_TYPE_CONTEXT
 #define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context
 
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
new file mode 100644
index 00000000000..6f6a6af9587
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
@@ -0,0 +1,83 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-options "-march=armv8.2-a+i8mm" } */
+
+#include <arm_neon.h>
+
+bfloat16_t glob;
+float is_a_float;
+int n;
+
+bfloat16_t footest (bfloat16_t scalar0)
+{
+
+  /* Initialisation  */
+
+  bfloat16_t scalar1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'double'" "" {target *-*-*} } */
+  bfloat16_t scalar2 = 0;   /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'int'" "" {target *-*-*} } */
+  bfloat16_t scalar3 = {}; /* { dg-error "empty scalar initializer" "" {target *-*-*} } */
+
+  float16_t initi_a = scalar1; /* { dg-error "incompatible types when assigning to type 'float16_t' from type 'bfloat16_t'" "" {target *-*-*} } */
+  float16_t initi_b = { scalar1 }; /* { dg-error "incompatible types when assigning to type 'float16_t' from type 'bfloat16_t'" "" {target *-*-*} } */
+
+  /* Compound literals.  */
+
+  (bfloat16_t) {}; /* { dg-error "empty scalar initializer" "" {target *-*-*} } */
+  (bfloat16_t) { scalar1 };
+
+  (int) { scalar1 }; /* { dg-error "incompatible types when assigning to type 'int' from type 'bfloat16_t'" "" {target *-*-*} } */
+
+  /* Casting.  */
+
+  (void) scalar1;
+  (bfloat16_t) scalar1;
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16_t array_type[2];
+  extern bfloat16_t extern_array[];
+
+  bfloat16_t array[2];
+  bfloat16_t zero_length_array[0];
+  bfloat16_t empty_init_array[] = {};
+  typedef bfloat16_t vla_type[n];
+
+  struct struct1 {
+    bfloat16_t a;
+  };
+
+  union union1 {
+    bfloat16_t a;
+  };
+
+  /* Assignments.  */
+
+  n = scalar1; /* { dg-error "incompatible types when assigning to type 'int' from type 'bfloat16_t'" "" {target *-*-*} } */
+  is_a_float = scalar1; /* { dg-error "incompatible types when assigning to type 'float' from type 'bfloat16_t'" "" {target *-*-*} } */
+  scalar1 = 0; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'int'" "" {target *-*-*} } */
+  scalar1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'double'" "" {target *-*-*} } */
+  scalar1 = scalar2;
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16_t *bfloat_ptr = &scalar1;
+  scalar1 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16_t *bfloat_ptr2 = bfloat_ptr;
+
+  /* Single-operand operation.  */
+
+  scalar1 = !glob; /* { dg-error "operation not permitted on type 'bfloat16_t'" "" {target *-*-*} } */
+
+  /* Double-operand operations.  */
+
+  scalar1 = glob + *bfloat_ptr; /* { dg-error "operation not permitted on types 'bfloat16_t', 'bfloat16_t'" "" {target *-*-*} } */
+  scalar1 = glob + 0.1; /* { dg-error "operation not permitted on types 'bfloat16_t', 'double'" "" {target *-*-*} } */
+  scalar1 = glob + 0; /* { dg-error "operation not permitted on types 'bfloat16_t', 'int'" "" {target *-*-*} } */
+  scalar1 = glob + is_a_float; /* { dg-error "operation not permitted on types 'bfloat16_t', 'float'" "" {target *-*-*} } */
+
+  return scalar0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c
new file mode 100644
index 00000000000..06786d9daa9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c
@@ -0,0 +1,85 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-options "-march=armv8.2-a+i8mm" } */
+
+#include <arm_neon.h>
+
+bfloat16x4_t glob;
+float is_a_float;
+float16x4_t is_a_floatx4;
+int16x4_t intvec;
+int n;
+short n2;
+bfloat16_t scalar0, scalar1, scalar2, scalar3;
+
+bfloat16x4_t footest (bfloat16x4_t vector0)
+{
+  /* Initialisation  */
+
+  bfloat16x4_t vector1 = { 0.0, n, n2, is_a_float };
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'double'" "" {target *-*-*} 19 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'int'" "" {target *-*-*} 19 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'short int'" "" {target *-*-*} 19 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'float'" "" {target *-*-*} 19 } */
+
+  bfloat16x4_t vector2 = {};
+
+  (bfloat16x4_t) {};
+
+  bfloat16x4_t vector4 = { scalar0, scalar1, scalar2, scalar3 };
+
+  float16x4_t initi_a = vector1; /* { dg-error "incompatible types when initializing type 'float16x4_t' using type 'bfloat16x4_t'" "" {target *-*-*} } */
+
+  /* Casting.  */
+
+  (void) vector1;
+  (bfloat16x4_t) vector1;
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16x4_t array_type[2];
+  extern bfloat16x4_t extern_array[];
+
+  bfloat16x4_t array[2];
+  bfloat16x4_t zero_length_array[0];
+  bfloat16x4_t empty_init_array[] = {};
+  typedef bfloat16x4_t some_other_type[n];
+
+  struct struct1 {
+    bfloat16x4_t a;
+  };
+
+  union union1 {
+    bfloat16x4_t a;
+  };
+
+  /* Assignments.  */
+
+  intvec = vector1; /* { dg-error "incompatible types when assigning to type 'int16x4_t' from type 'bfloat16x4_t'" "" {target *-*-*} } */
+  is_a_floatx4 = vector1; /* { dg-error "incompatible types when assigning to type 'float16x4_t' from type 'bfloat16x4_t'" "" {target *-*-*} } */
+  vector1 = 0; /* { dg-error "incompatible types when assigning to type 'bfloat16x4_t' from type 'int'" "" {target *-*-*} } */
+  vector1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16x4_t' from type 'double'" "" {target *-*-*} } */
+  vector1 = vector2;
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16x4_t *bfloat_ptr = &vector1;
+  vector1 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16x4_t *bfloat_ptr2 = bfloat_ptr;
+
+  /* Single-operand operation.  */
+
+  vector1 = !glob; /* { dg-error "operation not permitted on type 'bfloat16x4_t'" "" {target *-*-*} } */
+
+  /* Double-operand operations.  */
+
+  vector1 = glob + *bfloat_ptr; /* { dg-error "operation not permitted on types 'bfloat16x4_t', 'bfloat16x4_t'" "" {target *-*-*} } */
+  vector1 = glob + 0.1; /* { dg-error "operation not permitted on types 'bfloat16x4_t', 'double'" "" {target *-*-*} } */
+  vector1 = glob + 0; /* { dg-error "operation not permitted on types 'bfloat16x4_t', 'int'" "" {target *-*-*} } */
+  vector1 = glob + is_a_floatx4; /* { dg-error "operation not permitted on types 'bfloat16x4_t', 'float16x4_t'" "" {target *-*-*} } */
+
+  return vector0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck2.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck2.c
new file mode 100644
index 00000000000..3be3e0551b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck2.c
@@ -0,0 +1,95 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-options "-march=armv8.2-a+i8mm" } */
+
+#include <arm_neon.h>
+
+bfloat16_t scalar0, scalar1, scalar2, scalar3;
+bfloat16x8_t glob;
+
+float16_t is_a_half_float;
+float16x8_t is_a_floatx8;
+int16x8_t intvec;
+
+float is_a_float;
+int is_an_int;
+unsigned int is_a_uint;
+short is_a_short_int;
+long is_long;
+long double is_long_double;
+
+bfloat16x8_t footest (bfloat16x8_t vector0)
+{
+  /* Initialisation  */
+
+  bfloat16x8_t vector1 = { 0.0, is_an_int, is_a_short_int, is_a_float, is_a_half_float, is_long, is_a_uint, is_long_double };
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'double'" "" {target *-*-*} 25 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'int'" "" {target *-*-*} 25 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'short int'" "" {target *-*-*} 25 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'float'" "" {target *-*-*} 25 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'float16_t'" "" {target *-*-*} 25 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'long int'" "" {target *-*-*} 25 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'unsigned int'" "" {target *-*-*} 25 } */
+  /* { dg-error "incompatible types when assigning to type '__bf16' from type 'long double'" "" {target *-*-*} 25 } */
+
+  bfloat16x8_t vector2 = {};
+
+  (bfloat16x8_t) {};
+
+  bfloat16x8_t vector4 = { scalar0, scalar1, scalar2, scalar3, scalar0, scalar1, scalar2, scalar3 };
+
+  float16x8_t initi_a = vector1; /* { dg-error "incompatible types when initializing type 'float16x8_t' using type 'bfloat16x8_t'" "" {target *-*-*} } */
+
+  /* Casting.  */
+
+  (void) vector1;
+  (bfloat16x8_t) vector1;
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16x8_t array_type[2];
+  extern bfloat16x8_t extern_array[];
+
+  bfloat16x8_t array[2];
+  bfloat16x8_t zero_length_array[0];
+  bfloat16x8_t empty_init_array[] = {};
+  typedef bfloat16x8_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16x8_t a;
+  };
+
+  union union1 {
+    bfloat16x8_t a;
+  };
+
+  /* Assignments.  */
+
+  intvec = vector1; /* { dg-error "incompatible types when assigning to type 'int16x8_t' from type 'bfloat16x8_t'" "" {target *-*-*} } */
+  is_a_floatx8 = vector1; /* { dg-error "incompatible types when assigning to type 'float16x8_t' from type 'bfloat16x8_t'" "" {target *-*-*} } */
+  vector1 = 0; /* { dg-error "incompatible types when assigning to type 'bfloat16x8_t' from type 'int'" "" {target *-*-*} } */
+  vector1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16x8_t' from type 'double'" "" {target *-*-*} } */
+  vector1 = vector2;
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16x8_t *bfloat_ptr = &vector1;
+  vector1 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16x8_t *bfloat_ptr2 = bfloat_ptr;
+
+  /* Single-operand operation.  */
+
+  vector1 = !glob; /* { dg-error "operation not permitted on type 'bfloat16x8_t'" "" {target *-*-*} } */
+
+  /* Double-operand operations.  */
+
+  vector1 = glob + *bfloat_ptr; /* { dg-error "operation not permitted on types 'bfloat16x8_t', 'bfloat16x8_t'" "" {target *-*-*} } */
+  vector1 = glob + 0.1; /* { dg-error "operation not permitted on types 'bfloat16x8_t', 'double'" "" {target *-*-*} } */
+  vector1 = glob + 0; /* { dg-error "operation not permitted on types 'bfloat16x8_t', 'int'" "" {target *-*-*} } */
+  vector1 = glob + is_a_floatx8; /* { dg-error "operation not permitted on types 'bfloat16x8_t', 'float16x8_t'" "" {target *-*-*} } */
+
+  return vector0;
+}


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
  2019-12-18 16:40 [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2] Stam Markianos-Wright
@ 2019-12-19 10:10 ` Richard Sandiford
  2020-01-07 11:42   ` Stam Markianos-Wright
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Sandiford @ 2019-12-19 10:10 UTC (permalink / raw)
  To: Stam Markianos-Wright
  Cc: gcc-patches, Richard Earnshaw, Kyrylo Tkachov, Marcus Shawcroft

Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index f57469b6e23..f40f6432fd4 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -21661,6 +21661,68 @@ aarch64_stack_protect_guard (void)
>    return NULL_TREE;
>  }
>  
> +/* Return the diagnostic message string if conversion from FROMTYPE to
> +   TOTYPE is not allowed, NULL otherwise.  */
> +
> +static const char *
> +aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
> +{
> +  static char templ[100];
> +  if ((GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode
> +       || GET_MODE_INNER (TYPE_MODE (totype)) == BFmode)
> +       && TYPE_MODE (fromtype) != TYPE_MODE (totype))
> +  {
> +    snprintf (templ, sizeof (templ), \
> +      "incompatible types when assigning to type '%s' from type '%s'",
> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (totype))),
> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (fromtype))));
> +    return N_(templ);
> +  }
> +  /* Conversion allowed.  */
> +  return NULL;
> +}
> +

This won't handle translation properly.  We also have no guarantee that
the formatted string will fit in 100 characters since at least one of
the type names is unconstrained.  (Also, not all types have names.)

Unfortunately the interface of the current hook doesn't allow for good
diagnostics.  We'll just have to return a fixed string.

Formatting nit: braced block should be indented two spaces more
than the "if (...)".

Same comment for the other hooks.

> +/* Return the diagnostic message string if the unary operation OP is
> +   not permitted on TYPE, NULL otherwise.  */
> +
> +static const char *
> +aarch64_invalid_unary_op (int op, const_tree type)
> +{
> +  static char templ[100];
> +  /* Reject all single-operand operations on BFmode except for &.  */
> +  if (GET_MODE_INNER (TYPE_MODE (type)) == BFmode && op != ADDR_EXPR)
> +  {
> +    snprintf (templ, sizeof (templ),
> +      "operation not permitted on type '%s'",
> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
> +    return N_(templ);
> +  }
> +  /* Operation allowed.  */
> +  return NULL;
> +}

The problem with testing TYPE_MODE is that we'll then miss things
that don't have a dedicated mode.  E.g. it'd be interesting to
test what happens for arithmetic on:

  typedef bfloat16_t v16bf __attribute__((vector_size(32)));

Probably better to use element_mode instead.

> diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
> new file mode 100644
> index 00000000000..6f6a6af9587
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
> @@ -0,0 +1,83 @@
> +/* { dg-do compile { target { aarch64*-*-* } } } */
> +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
> +/* { dg-options "-march=armv8.2-a+i8mm" } */

+bf16 rather than +i8mm.  But using:

/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
/* { dg-add-options arm_v8_2a_bf16_neon }  */

would be better.

> +
> +#include <arm_neon.h>
> +
> +bfloat16_t glob;
> +float is_a_float;
> +int n;
> +
> +bfloat16_t footest (bfloat16_t scalar0)
> +{
> +
> +  /* Initialisation  */
> +
> +  bfloat16_t scalar1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'double'" "" {target *-*-*} } */
> +  bfloat16_t scalar2 = 0;   /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'int'" "" {target *-*-*} } */
> +  bfloat16_t scalar3 = {}; /* { dg-error "empty scalar initializer" "" {target *-*-*} } */

Would also be worth testing { scalar0 }, { is_a_float } and { 0.1 }.

(For SVE the tests are divided between sizeless_1.c and gnu_vectors_1.c.
Most of the cases mentioned here are handled in gnu_vectors_1.c instead.)

> +
> +  float16_t initi_a = scalar1; /* { dg-error "incompatible types when assigning to type 'float16_t' from type 'bfloat16_t'" "" {target *-*-*} } */
> +  float16_t initi_b = { scalar1 }; /* { dg-error "incompatible types when assigning to type 'float16_t' from type 'bfloat16_t'" "" {target *-*-*} } */
> +
> +  /* Compound literals.  */
> +
> +  (bfloat16_t) {}; /* { dg-error "empty scalar initializer" "" {target *-*-*} } */
> +  (bfloat16_t) { scalar1 };

Same here.

> +
> +  (int) { scalar1 }; /* { dg-error "incompatible types when assigning to type 'int' from type 'bfloat16_t'" "" {target *-*-*} } */
> +
> +  /* Casting.  */
> +
> +  (void) scalar1;
> +  (bfloat16_t) scalar1;

Would be good to have some tests for invalid cases too.

> +
> +  /* Arrays and Structs.  */
> +
> +  typedef bfloat16_t array_type[2];
> +  extern bfloat16_t extern_array[];
> +
> +  bfloat16_t array[2];
> +  bfloat16_t zero_length_array[0];
> +  bfloat16_t empty_init_array[] = {};
> +  typedef bfloat16_t vla_type[n];
> +
> +  struct struct1 {
> +    bfloat16_t a;
> +  };
> +
> +  union union1 {
> +    bfloat16_t a;
> +  };
> +
> +  /* Assignments.  */
> +
> +  n = scalar1; /* { dg-error "incompatible types when assigning to type 'int' from type 'bfloat16_t'" "" {target *-*-*} } */
> +  is_a_float = scalar1; /* { dg-error "incompatible types when assigning to type 'float' from type 'bfloat16_t'" "" {target *-*-*} } */
> +  scalar1 = 0; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'int'" "" {target *-*-*} } */
> +  scalar1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'double'" "" {target *-*-*} } */
> +  scalar1 = scalar2;

Would be good to test the other way too: "scalar1 = is_a_float",
"scalar1 = n".

> +
> +  /* Addressing and dereferencing.  */
> +
> +  bfloat16_t *bfloat_ptr = &scalar1;
> +  scalar1 = *bfloat_ptr;
> +
> +  /* Pointer assignment.  */
> +
> +  bfloat16_t *bfloat_ptr2 = bfloat_ptr;
> +
> +  /* Single-operand operation.  */
> +
> +  scalar1 = !glob; /* { dg-error "operation not permitted on type 'bfloat16_t'" "" {target *-*-*} } */

Would be good to test "+" and "-" as well -- "!" isn't really typical
for floats.

Other things worth testing for are:

- comparisons
- bfloats used as a condition (e.g. bfloat16 ? a : b)
- bfloats selected via ?:, including cases where the types don't match

> [...]
> diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c

Very minor, but local aarch64 style seems to be to use foo_1, foo_2,
etc. rather than foo, foo1, etc., although things aren't very consistent.

Similar comments for these tests as for the scalar ones.

It would be good to have C++ tests too.  An extra thing to test there
is elementwise vector ? vector : vector.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
  2019-12-19 10:10 ` Richard Sandiford
@ 2020-01-07 11:42   ` Stam Markianos-Wright
  2020-01-07 15:26     ` Richard Sandiford
  0 siblings, 1 reply; 10+ messages in thread
From: Stam Markianos-Wright @ 2020-01-07 11:42 UTC (permalink / raw)
  To: gcc-patches, Richard Earnshaw, Kyrylo Tkachov, Marcus Shawcroft,
	Richard Sandiford



On 12/19/19 10:08 AM, Richard Sandiford wrote:
> Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
>> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
>> index f57469b6e23..f40f6432fd4 100644
>> --- a/gcc/config/aarch64/aarch64.c
>> +++ b/gcc/config/aarch64/aarch64.c
>> @@ -21661,6 +21661,68 @@ aarch64_stack_protect_guard (void)
>>     return NULL_TREE;
>>   }
>>   
>> +/* Return the diagnostic message string if conversion from FROMTYPE to
>> +   TOTYPE is not allowed, NULL otherwise.  */
>> +
>> +static const char *
>> +aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
>> +{
>> +  static char templ[100];
>> +  if ((GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode
>> +       || GET_MODE_INNER (TYPE_MODE (totype)) == BFmode)
>> +       && TYPE_MODE (fromtype) != TYPE_MODE (totype))
>> +  {
>> +    snprintf (templ, sizeof (templ), \
>> +      "incompatible types when assigning to type '%s' from type '%s'",
>> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (totype))),
>> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (fromtype))));
>> +    return N_(templ);
>> +  }
>> +  /* Conversion allowed.  */
>> +  return NULL;
>> +}
>> +
> 
> This won't handle translation properly.  We also have no guarantee that
> the formatted string will fit in 100 characters since at least one of
> the type names is unconstrained.  (Also, not all types have names.)
> 

Hi Richard. I'm sending an email here to show you what I have done here, too :)

Currently I have the following:

static const char *
aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
{
   static char templ[100];
   if (TYPE_MODE (fromtype) != TYPE_MODE (totype)
       && ((TYPE_MODE (fromtype) == BFmode && !VECTOR_TYPE_P (fromtype))
	  || (TYPE_MODE (totype) == BFmode && !VECTOR_TYPE_P (totype))))
     {
       if (TYPE_NAME (fromtype) != NULL && TYPE_NAME (totype) != NULL)
	{
	  snprintf (templ, sizeof (templ),
	    "incompatible types when assigning to type '%s' from type '%s'",
	    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (totype))),
	    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (fromtype))));
	  return N_(templ);
	}
       else
	{
	  snprintf (templ, sizeof (templ),
	    "incompatible types for assignment");
	  return N_(templ);
	}
     }
   /* Conversion allowed.  */
   return NULL;
}

This blocks the conversion only if the two types are of different modes and one 
of them is a BFmode scalar.

Doing it like this seems to block all scalar-sized assignments:

C:

typedef bfloat16_t vbf __attribute__((vector_size(2)));
vbf foo3 (void) { return (vbf) 0x1234; }

bfloat16_t foo1 (void) { return (bfloat16_t) 0x1234; }

bfloat16_t scalar1_3 = 0;
bfloat16_t scalar1_4 = 0.1;
bfloat16_t scalar1_5 = is_a_float;

bfloat16x4_t vector2_8 = { 0.0, 0, n2, is_a_float }; // (blocked on each element 
assignment)


C++:

bfloat16_t c1 (void) { return bfloat16_t (0x1234); }

bfloat16_t c2 (void) { return bfloat16_t (0.1); }


But then it allows vector initialisation from binary:

C:
bfloat16x4_t foo1 (void) { return (bfloat16x4_t) 0x1234567812345678; }

C++:
bfloat16x4_t foo1 (void) { return bfloat16x4_t (0x1234567812345678); }
typedef bfloat16_t v2bf __attribute__((vector_size(4)));
v2bf foo3 (void) { return v2bf (0x12345678); }

I also need to check with a colleague who is on holiday if any of this impacts 
the vector-reinterpret intrinsics that he was working on...

Let me know of your thoughts!

Cheers,
Stam

> Unfortunately the interface of the current hook doesn't allow for good
> diagnostics.  We'll just have to return a fixed string. >
> Formatting nit: braced block should be indented two spaces more
> than the "if (...)".
> 
> Same comment for the other hooks.

Done. Will be in next revision

> 
>> +/* Return the diagnostic message string if the unary operation OP is
>> +   not permitted on TYPE, NULL otherwise.  */
>> +
>> +static const char *
>> +aarch64_invalid_unary_op (int op, const_tree type)
>> +{
>> +  static char templ[100];
>> +  /* Reject all single-operand operations on BFmode except for &.  */
>> +  if (GET_MODE_INNER (TYPE_MODE (type)) == BFmode && op != ADDR_EXPR)
>> +  {
>> +    snprintf (templ, sizeof (templ),
>> +      "operation not permitted on type '%s'",
>> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
>> +    return N_(templ);
>> +  }
>> +  /* Operation allowed.  */
>> +  return NULL;
>> +}
> 
> The problem with testing TYPE_MODE is that we'll then miss things
> that don't have a dedicated mode.  E.g. it'd be interesting to
> test what happens for arithmetic on:
> 
>    typedef bfloat16_t v16bf __attribute__((vector_size(32)));
> 
> Probably better to use element_mode instead.

Done. Will be in next revision

> 
>> diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
>> new file mode 100644
>> index 00000000000..6f6a6af9587
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
>> @@ -0,0 +1,83 @@
>> +/* { dg-do compile { target { aarch64*-*-* } } } */
>> +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
>> +/* { dg-options "-march=armv8.2-a+i8mm" } */
> 
> +bf16 rather than +i8mm.  But using:
> 
> /* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
> /* { dg-add-options arm_v8_2a_bf16_neon }  */
> 
> would be better.

Done. Will be in next revision
> 
>> +
>> +#include <arm_neon.h>
>> +
>> +bfloat16_t glob;
>> +float is_a_float;
>> +int n;
>> +
>> +bfloat16_t footest (bfloat16_t scalar0)
>> +{
>> +
>> +  /* Initialisation  */
>> +
>> +  bfloat16_t scalar1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'double'" "" {target *-*-*} } */
>> +  bfloat16_t scalar2 = 0;   /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'int'" "" {target *-*-*} } */
>> +  bfloat16_t scalar3 = {}; /* { dg-error "empty scalar initializer" "" {target *-*-*} } */
> 
> Would also be worth testing { scalar0 }, { is_a_float } and { 0.1 }.

Done. Will be in next revision

> 
> (For SVE the tests are divided between sizeless_1.c and gnu_vectors_1.c.
> Most of the cases mentioned here are handled in gnu_vectors_1.c instead.)
> 
>> +
>> +  float16_t initi_a = scalar1; /* { dg-error "incompatible types when assigning to type 'float16_t' from type 'bfloat16_t'" "" {target *-*-*} } */
>> +  float16_t initi_b = { scalar1 }; /* { dg-error "incompatible types when assigning to type 'float16_t' from type 'bfloat16_t'" "" {target *-*-*} } */
>> +
>> +  /* Compound literals.  */
>> +
>> +  (bfloat16_t) {}; /* { dg-error "empty scalar initializer" "" {target *-*-*} } */
>> +  (bfloat16_t) { scalar1 };
> 
> Same here.

Done. Will be in next revision

> 
>> +
>> +  (int) { scalar1 }; /* { dg-error "incompatible types when assigning to type 'int' from type 'bfloat16_t'" "" {target *-*-*} } */
>> +
>> +  /* Casting.  */
>> +
>> +  (void) scalar1;
>> +  (bfloat16_t) scalar1;
> 
> Would be good to have some tests for invalid cases too.

Done. Will be in next revision

> 
>> +
>> +  /* Arrays and Structs.  */
>> +
>> +  typedef bfloat16_t array_type[2];
>> +  extern bfloat16_t extern_array[];
>> +
>> +  bfloat16_t array[2];
>> +  bfloat16_t zero_length_array[0];
>> +  bfloat16_t empty_init_array[] = {};
>> +  typedef bfloat16_t vla_type[n];
>> +
>> +  struct struct1 {
>> +    bfloat16_t a;
>> +  };
>> +
>> +  union union1 {
>> +    bfloat16_t a;
>> +  };
>> +
>> +  /* Assignments.  */
>> +
>> +  n = scalar1; /* { dg-error "incompatible types when assigning to type 'int' from type 'bfloat16_t'" "" {target *-*-*} } */
>> +  is_a_float = scalar1; /* { dg-error "incompatible types when assigning to type 'float' from type 'bfloat16_t'" "" {target *-*-*} } */
>> +  scalar1 = 0; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'int'" "" {target *-*-*} } */
>> +  scalar1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'double'" "" {target *-*-*} } */
>> +  scalar1 = scalar2;
> 
> Would be good to test the other way too: "scalar1 = is_a_float",
> "scalar1 = n".

Done. Will be in next revision

> 
>> +
>> +  /* Addressing and dereferencing.  */
>> +
>> +  bfloat16_t *bfloat_ptr = &scalar1;
>> +  scalar1 = *bfloat_ptr;
>> +
>> +  /* Pointer assignment.  */
>> +
>> +  bfloat16_t *bfloat_ptr2 = bfloat_ptr;
>> +
>> +  /* Single-operand operation.  */
>> +
>> +  scalar1 = !glob; /* { dg-error "operation not permitted on type 'bfloat16_t'" "" {target *-*-*} } */
> 
> Would be good to test "+" and "-" as well -- "!" isn't really typical
> for floats.
> 

Done. Will be in next revision

> Other things worth testing for are:
> 
> - comparisons
> - bfloats used as a condition (e.g. bfloat16 ? a : b)
> - bfloats selected via ?:, including cases where the types don't match
> 

Done. Will be in next revision

>> [...]
>> diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c
> 
> Very minor, but local aarch64 style seems to be to use foo_1, foo_2,
> etc. rather than foo, foo1, etc., although things aren't very consistent.

Done. Will be in next revision

> 
> Similar comments for these tests as for the scalar ones.
> 
> It would be good to have C++ tests too.  An extra thing to test there
> is elementwise vector ? vector : vector.

Done. Will be in next revision

> 
> Thanks,
> Richard
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
  2020-01-07 11:42   ` Stam Markianos-Wright
@ 2020-01-07 15:26     ` Richard Sandiford
  2020-01-09 15:03       ` Stam Markianos-Wright
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Sandiford @ 2020-01-07 15:26 UTC (permalink / raw)
  To: Stam Markianos-Wright
  Cc: gcc-patches, Richard Earnshaw, Kyrylo Tkachov, Marcus Shawcroft

Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
> On 12/19/19 10:08 AM, Richard Sandiford wrote:
>> Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
>>> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
>>> index f57469b6e23..f40f6432fd4 100644
>>> --- a/gcc/config/aarch64/aarch64.c
>>> +++ b/gcc/config/aarch64/aarch64.c
>>> @@ -21661,6 +21661,68 @@ aarch64_stack_protect_guard (void)
>>>     return NULL_TREE;
>>>   }
>>>   
>>> +/* Return the diagnostic message string if conversion from FROMTYPE to
>>> +   TOTYPE is not allowed, NULL otherwise.  */
>>> +
>>> +static const char *
>>> +aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
>>> +{
>>> +  static char templ[100];
>>> +  if ((GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode
>>> +       || GET_MODE_INNER (TYPE_MODE (totype)) == BFmode)
>>> +       && TYPE_MODE (fromtype) != TYPE_MODE (totype))
>>> +  {
>>> +    snprintf (templ, sizeof (templ), \
>>> +      "incompatible types when assigning to type '%s' from type '%s'",
>>> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (totype))),
>>> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (fromtype))));
>>> +    return N_(templ);
>>> +  }
>>> +  /* Conversion allowed.  */
>>> +  return NULL;
>>> +}
>>> +
>> 
>> This won't handle translation properly.  We also have no guarantee that
>> the formatted string will fit in 100 characters since at least one of
>> the type names is unconstrained.  (Also, not all types have names.)
>> 
>
> Hi Richard. I'm sending an email here to show you what I have done here, too :)
>
> Currently I have the following:
>
> static const char *
> aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
> {
>    static char templ[100];
>    if (TYPE_MODE (fromtype) != TYPE_MODE (totype)
>        && ((TYPE_MODE (fromtype) == BFmode && !VECTOR_TYPE_P (fromtype))
> 	  || (TYPE_MODE (totype) == BFmode && !VECTOR_TYPE_P (totype))))

Just:

    if (TYPE_MODE (fromtype) != TYPE_MODE (totype)
        && (TYPE_MODE (fromtype) == BFmode || TYPE_MODE (fromtype) == BFmode))

should be enough.  Types that have BFmode can't also be vectors.

>      {
>        if (TYPE_NAME (fromtype) != NULL && TYPE_NAME (totype) != NULL)
> 	{
> 	  snprintf (templ, sizeof (templ),
> 	    "incompatible types when assigning to type '%s' from type '%s'",
> 	    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (totype))),
> 	    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (fromtype))));
> 	  return N_(templ);
> 	}
>        else
> 	{
> 	  snprintf (templ, sizeof (templ),
> 	    "incompatible types for assignment");
> 	  return N_(templ);
> 	}

This still has the problem I mentioned above though: DECL_NAMEs are
supplied by the user and can be arbitrary lengths, so there's no
guarantee that the error message fits in the 100-character buffer.
We would get a truncated message if the buffer isn't big enough.

As far as translation goes: the arguments to diagnostic functions
like "error" are untranslated strings, which the diagnostic functions
then translate internally.  po/exgettext scans the source tree looking
for strings that need to be translatable and collects them all in po/gcc.pot.
Constant format strings in calls to known diagnostic functions get picked
up automatically (see ABOUT-GCC-NLS), but others need to be marked with
N_().  This N_() is simply a no-op wrapper macro that marks the argument
as needing translation.  It has no effect if the argument isn't a
constant string.

The interface of this hook is to return an untranslated diagnostic string
that gets passed to error.  A better interface would be to let the hook
raise its own error and return a boolean result, but that isn't what
we have.

So in the above, it's "incompatible types for assignment" that needs to
be wrapped in N_().  Wrapping templ has no effect.

This is also why the first arm doesn't work for translation.  It constructs
and returns an arbitrary new string that won't have been entered into
gcc.pot (and can't be, since it depends on the names of the user types).
So the error function will have no chance to translate it.  And it would
be a layering violation to try to translate it here.

So the hook basically has to return fixed strings marked with N_().
I don't think it should mention assignment though, since the conversions
could occur in any context (initialisation, function calls, etc.).  If
"invalid conversion" seems too terse, maybe we could have things like:

  "invalid conversion to %<bfloat16_t%>"

and:

  "invalid conversion to %<bfloat16_t%>"

>      }
>    /* Conversion allowed.  */
>    return NULL;
> }
>
> This blocks the conversion only if the two types are of different modes and one 
> of them is a BFmode scalar.
>
> Doing it like this seems to block all scalar-sized assignments:
>
> C:
>
> typedef bfloat16_t vbf __attribute__((vector_size(2)));
> vbf foo3 (void) { return (vbf) 0x1234; }
>
> bfloat16_t foo1 (void) { return (bfloat16_t) 0x1234; }
>
> bfloat16_t scalar1_3 = 0;
> bfloat16_t scalar1_4 = 0.1;
> bfloat16_t scalar1_5 = is_a_float;
>
> bfloat16x4_t vector2_8 = { 0.0, 0, n2, is_a_float }; // (blocked on each element 
> assignment)
>
>
> C++:
>
> bfloat16_t c1 (void) { return bfloat16_t (0x1234); }
>
> bfloat16_t c2 (void) { return bfloat16_t (0.1); }
>
>
> But then it allows vector initialisation from binary:
>
> C:
> bfloat16x4_t foo1 (void) { return (bfloat16x4_t) 0x1234567812345678; }
>
> C++:
> bfloat16x4_t foo1 (void) { return bfloat16x4_t (0x1234567812345678); }
> typedef bfloat16_t v2bf __attribute__((vector_size(4)));
> v2bf foo3 (void) { return v2bf (0x12345678); }
>
> I also need to check with a colleague who is on holiday if any of this impacts 
> the vector-reinterpret intrinsics that he was working on...
>
> Let me know of your thoughts!

Sounds good to me.  I hadn't realised when talking about the "(vector) int"
thing that this hook would block it, and TBH it probably isn't important
enough to go out of our way to unblock it.  But I think this is also the
behaviour we want for vector-vector conversions, which definitely are
important.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
  2020-01-07 15:26     ` Richard Sandiford
@ 2020-01-09 15:03       ` Stam Markianos-Wright
  2020-01-09 16:13         ` Richard Sandiford
  0 siblings, 1 reply; 10+ messages in thread
From: Stam Markianos-Wright @ 2020-01-09 15:03 UTC (permalink / raw)
  To: gcc-patches, Richard Earnshaw, Kyrylo Tkachov, Marcus Shawcroft,
	Richard Sandiford

[-- Attachment #1: Type: text/plain, Size: 7671 bytes --]



On 1/7/20 3:26 PM, Richard Sandiford wrote:
> Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
>> On 12/19/19 10:08 AM, Richard Sandiford wrote:
>>> Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
>>>> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
>>>> index f57469b6e23..f40f6432fd4 100644
>>>> --- a/gcc/config/aarch64/aarch64.c
>>>> +++ b/gcc/config/aarch64/aarch64.c
>>>> @@ -21661,6 +21661,68 @@ aarch64_stack_protect_guard (void)
>>>>      return NULL_TREE;
>>>>    }
>>>>    
>>>> +/* Return the diagnostic message string if conversion from FROMTYPE to
>>>> +   TOTYPE is not allowed, NULL otherwise.  */
>>>> +
>>>> +static const char *
>>>> +aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
>>>> +{
>>>> +  static char templ[100];
>>>> +  if ((GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode
>>>> +       || GET_MODE_INNER (TYPE_MODE (totype)) == BFmode)
>>>> +       && TYPE_MODE (fromtype) != TYPE_MODE (totype))
>>>> +  {
>>>> +    snprintf (templ, sizeof (templ), \
>>>> +      "incompatible types when assigning to type '%s' from type '%s'",
>>>> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (totype))),
>>>> +      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (fromtype))));
>>>> +    return N_(templ);
>>>> +  }
>>>> +  /* Conversion allowed.  */
>>>> +  return NULL;
>>>> +}
>>>> +
>>>
>>> This won't handle translation properly.  We also have no guarantee that
>>> the formatted string will fit in 100 characters since at least one of
>>> the type names is unconstrained.  (Also, not all types have names.)
>>>
>>
>> Hi Richard. I'm sending an email here to show you what I have done here, too :)
>>
>> Currently I have the following:
>>
>> static const char *
>> aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
>> {
>>     static char templ[100];
>>     if (TYPE_MODE (fromtype) != TYPE_MODE (totype)
>>         && ((TYPE_MODE (fromtype) == BFmode && !VECTOR_TYPE_P (fromtype))
>> 	  || (TYPE_MODE (totype) == BFmode && !VECTOR_TYPE_P (totype))))
> 
> Just:
> 
>      if (TYPE_MODE (fromtype) != TYPE_MODE (totype)
>          && (TYPE_MODE (fromtype) == BFmode || TYPE_MODE (fromtype) == BFmode))
> 
> should be enough.  Types that have BFmode can't also be vectors.

Yep, agreed.

> 
>>       {
>>         if (TYPE_NAME (fromtype) != NULL && TYPE_NAME (totype) != NULL)
>> 	{
>> 	  snprintf (templ, sizeof (templ),
>> 	    "incompatible types when assigning to type '%s' from type '%s'",
>> 	    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (totype))),
>> 	    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (fromtype))));
>> 	  return N_(templ);
>> 	}
>>         else
>> 	{
>> 	  snprintf (templ, sizeof (templ),
>> 	    "incompatible types for assignment");
>> 	  return N_(templ);
>> 	}
> 
> This still has the problem I mentioned above though: DECL_NAMEs are
> supplied by the user and can be arbitrary lengths, so there's no
> guarantee that the error message fits in the 100-character buffer.
> We would get a truncated message if the buffer isn't big enough.
> 
> As far as translation goes: the arguments to diagnostic functions
> like "error" are untranslated strings, which the diagnostic functions
> then translate internally.  po/exgettext scans the source tree looking
> for strings that need to be translatable and collects them all in po/gcc.pot.
> Constant format strings in calls to known diagnostic functions get picked
> up automatically (see ABOUT-GCC-NLS), but others need to be marked with
> N_().  This N_() is simply a no-op wrapper macro that marks the argument
> as needing translation.  It has no effect if the argument isn't a
> constant string.
> 
> The interface of this hook is to return an untranslated diagnostic string
> that gets passed to error.  A better interface would be to let the hook
> raise its own error and return a boolean result, but that isn't what
> we have.
> 
> So in the above, it's "incompatible types for assignment" that needs to
> be wrapped in N_().  Wrapping templ has no effect.
> 
> This is also why the first arm doesn't work for translation.  It constructs
> and returns an arbitrary new string that won't have been entered into
> gcc.pot (and can't be, since it depends on the names of the user types).
> So the error function will have no chance to translate it.  And it would
> be a layering violation to try to translate it here.
> 
> So the hook basically has to return fixed strings marked with N_().
> I don't think it should mention assignment though, since the conversions
> could occur in any context (initialisation, function calls, etc.).  If
> "invalid conversion" seems too terse, maybe we could have things like:
> 
>    "invalid conversion to %<bfloat16_t%>"
> 
> and:
> 
>    "invalid conversion to %<bfloat16_t%>"
> 

Oh ok I think I get you now (I was totally not aware of how this worked, as you 
probably guessed!).

I have simplified it now as you suggested (in all 3 target hooks).

Also updated all the tests to check for correct behaviour as per below and added 
a few more checks to make the tests more robust as per our previous emails.

Also added a small c++ test for bfloat16_t(); behaviour. One nit here:
By the time the compiler reaches our target hook for just "bfloat16_t ();" it 
thinks that fromtype is an SImode constant 0.

With sume debugging I've seen that the whole raw printout of the type tree of 
fromtype is identical for "bfloat16_t ();" and "bfloat16_t (0x1234);" or eveb 
"bfloat16_t (5);", so it looks like our target hook won't be able to 
differentiate between the two... Do you have any ideas for this? (Or we just 
leave it as blocked, which is a bit weird)

Let me know if you notice I've missed anything else!


>>       }
>>     /* Conversion allowed.  */
>>     return NULL;
>> }
>>
>> This blocks the conversion only if the two types are of different modes and one
>> of them is a BFmode scalar.
>>
>> Doing it like this seems to block all scalar-sized assignments:
>>
>> C:
>>
>> typedef bfloat16_t vbf __attribute__((vector_size(2)));
>> vbf foo3 (void) { return (vbf) 0x1234; }
>>
>> bfloat16_t foo1 (void) { return (bfloat16_t) 0x1234; }
>>
>> bfloat16_t scalar1_3 = 0;
>> bfloat16_t scalar1_4 = 0.1;
>> bfloat16_t scalar1_5 = is_a_float;
>>
>> bfloat16x4_t vector2_8 = { 0.0, 0, n2, is_a_float }; // (blocked on each element
>> assignment)
>>
>>
>> C++:
>>
>> bfloat16_t c1 (void) { return bfloat16_t (0x1234); }
>>
>> bfloat16_t c2 (void) { return bfloat16_t (0.1); }
>>
>>
>> But then it allows vector initialisation from binary:
>>
>> C:
>> bfloat16x4_t foo1 (void) { return (bfloat16x4_t) 0x1234567812345678; }
>>
>> C++:
>> bfloat16x4_t foo1 (void) { return bfloat16x4_t (0x1234567812345678); }
>> typedef bfloat16_t v2bf __attribute__((vector_size(4)));
>> v2bf foo3 (void) { return v2bf (0x12345678); }
>>
>> I also need to check with a colleague who is on holiday if any of this impacts
>> the vector-reinterpret intrinsics that he was working on...
>>
>> Let me know of your thoughts!
> 
> Sounds good to me.  I hadn't realised when talking about the "(vector) int"
> thing that this hook would block it, and TBH it probably isn't important
> enough to go out of our way to unblock it.  But I think this is also the
> behaviour we want for vector-vector conversions, which definitely are
> important.

Amazing. The other pro of this is that we are now as close as we can be to clang 
behaviour, too :)


> 
> Thanks,
> Richard
> 

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: BFmode2of2.patch --]
[-- Type: text/x-patch; name="BFmode2of2.patch", Size: 53882 bytes --]

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index ebd3f6cf45b..ce410ddf551 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -21760,6 +21760,55 @@ aarch64_stack_protect_guard (void)
   return NULL_TREE;
 }
 
+/* Return the diagnostic message string if conversion from FROMTYPE to
+   TOTYPE is not allowed, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
+{
+  if (element_mode (fromtype) != element_mode (totype))
+    {
+      /* Do no allow conversions to/from BFmode scalar types.  */
+      if (TYPE_MODE (fromtype) == BFmode)
+	return N_("invalid conversion from type %<bfloat16_t%>");
+      if (TYPE_MODE (totype) == BFmode)
+	return N_("invalid conversion to type %<bfloat16_t%>");
+    }
+
+  /* Conversion allowed.  */
+  return NULL;
+}
+
+/* Return the diagnostic message string if the unary operation OP is
+   not permitted on TYPE, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_unary_op (int op, const_tree type)
+{
+  /* Reject all single-operand operations on BFmode except for &.  */
+  if (element_mode (type) == BFmode && op != ADDR_EXPR)
+    return N_("operation not permitted on type %<bfloat16_t%>");
+
+  /* Operation allowed.  */
+  return NULL;
+}
+
+/* Return the diagnostic message string if the binary operation OP is
+   not permitted on TYPE1 and TYPE2, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
+			   const_tree type2)
+{
+  /* Reject all 2-operand operations on BFmode.  */
+  if (element_mode (type1) == BFmode
+      || element_mode (type2) == BFmode)
+    return N_("operation not permitted on type %<bfloat16_t%>");
+
+  /* Operation allowed.  */
+  return NULL;
+}
+
 /* Implement TARGET_ASM_FILE_END for AArch64.  This adds the AArch64 GNU NOTE
    section at the end if needed.  */
 #define GNU_PROPERTY_AARCH64_FEATURE_1_AND	0xc0000000
@@ -22010,6 +22059,15 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE aarch64_mangle_type
 
+#undef TARGET_INVALID_CONVERSION
+#define TARGET_INVALID_CONVERSION aarch64_invalid_conversion
+
+#undef TARGET_INVALID_UNARY_OP
+#define TARGET_INVALID_UNARY_OP aarch64_invalid_unary_op
+
+#undef TARGET_INVALID_BINARY_OP
+#define TARGET_INVALID_BINARY_OP aarch64_invalid_binary_op
+
 #undef TARGET_VERIFY_TYPE_CONTEXT
 #define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context
 
diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
new file mode 100644
index 00000000000..55cbb0b0ef7
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
@@ -0,0 +1,14 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-O3 --save-temps" } */
+
+#include <arm_neon.h>
+
+void foo (void)
+{
+  bfloat16_t (); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t a = bfloat16_t(); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t (0x1234); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t (0.1); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
new file mode 100644
index 00000000000..5a9eda67411
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
@@ -0,0 +1,219 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-Wno-pedantic -O3 --save-temps" }  */
+
+#include <arm_neon.h>
+
+bfloat16_t glob_bfloat;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+double is_a_double;
+
+float *float_ptr;
+
+bfloat16_t foo1 (void) { return (bfloat16_t) 0x1234; } /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+bfloat16_t foo2 (void) { return (bfloat16_t) (short) 0x1234; } /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+
+bfloat16_t footest (bfloat16_t scalar0)
+{
+
+  /* Initialisation  */
+
+  bfloat16_t scalar1_1;
+  bfloat16_t scalar1_2 = glob_bfloat;
+  bfloat16_t scalar1_3 = 0;   /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar1_4 = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar1_5 = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar1_6 = is_an_int;  /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar1_8 = is_a_double; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+
+  int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float initi_1_2 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float16_t initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  short initi_1_4 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  double initi_1_5 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+
+  bfloat16_t scalar2_1 = {}; /* { dg-error {empty scalar initializer} "" {target *-*-*} } */
+  bfloat16_t scalar2_2 = { glob_bfloat };
+  bfloat16_t scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar2_7 = { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16_t scalar2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+
+  int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float16_t initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  short initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  double initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Assignments.  */
+
+  glob_bfloat = glob_bfloat;
+  glob_bfloat = 0;   /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  glob_bfloat = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  glob_bfloat = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  glob_bfloat = is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  glob_bfloat = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  glob_bfloat = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+
+  is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_float = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_double = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_short_int = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Casting.  */
+
+  (void) glob_bfloat;
+  (bfloat16_t) glob_bfloat;
+
+  (int) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  (float) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  (float16_t) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  (double) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  (short) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+
+  (bfloat16_t) is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) is_a_double; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Compound literals.  */
+
+  (bfloat16_t) {}; /* { dg-error {empty scalar initializer} "" {target *-*-*} } */
+  (bfloat16_t) { glob_bfloat };
+  (bfloat16_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) { is_a_double }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16_t) { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+
+  (int) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  (float) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  (float16_t) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  (double) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  (short) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16_t array_type[2];
+  extern bfloat16_t extern_array[];
+
+  bfloat16_t array[2];
+  bfloat16_t zero_length_array[0];
+  bfloat16_t empty_init_array[] = {};
+  typedef bfloat16_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16_t a;
+  };
+
+  union union1 {
+    bfloat16_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16_t *bfloat_ptr = &scalar0;
+  scalar0 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16_t *bfloat_ptr2 = bfloat_ptr;
+  bfloat16_t *bfloat_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++bfloat_ptr;
+  --bfloat_ptr;
+  bfloat_ptr++;
+  bfloat_ptr--;
+  bfloat_ptr += 1;
+  bfloat_ptr -= 1;
+  bfloat_ptr - bfloat_ptr2;
+  bfloat_ptr = &bfloat_ptr3[0];
+  bfloat_ptr = &bfloat_ptr3[1];
+
+  /* Simple comparison.  */
+  scalar0 > glob_bfloat; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  glob_bfloat == scalar0; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 > is_a_float; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_float == scalar0; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 > 0; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  0 == scalar0; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 > 0.1; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  0.1 == scalar0; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 > is_an_int; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  is_an_int == scalar0; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Pointer comparison.  */
+
+  bfloat_ptr == &scalar0;
+  bfloat_ptr != &scalar0;
+  bfloat_ptr < &scalar0;
+  bfloat_ptr <= &scalar0;
+  bfloat_ptr > &scalar0;
+  bfloat_ptr >= &scalar0;
+  bfloat_ptr == bfloat_ptr2;
+  bfloat_ptr != bfloat_ptr2;
+  bfloat_ptr < bfloat_ptr2;
+  bfloat_ptr <= bfloat_ptr2;
+  bfloat_ptr > bfloat_ptr2;
+  bfloat_ptr >= bfloat_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? scalar0 : scalar0;
+  0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  0 ? scalar0 : 0; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  0 ? 0 : scalar0; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  0 ? bfloat_ptr : bfloat_ptr2;
+  0 ? bfloat_ptr : float_ptr; /* { dg-error {pointer type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? float_ptr : bfloat_ptr; /* { dg-error {pointer type mismatch in conditional expression} "" {target *-*-*} } */
+
+  scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 ? is_a_float : scalar0; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Unary operators.  */
+
+  +scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  -scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  ~scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  !scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  *scalar0; /* { dg-error {invalid type argument of unary '\*'} "" {target *-*-*} } */
+  __real scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  __imag scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  ++scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  --scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0++; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0--; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Binary arithmetic operations.  */
+
+  scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+  scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not permitted using type 'bfloat16_t'} "" {target *-*-*} } */
+
+  return scalar0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c
new file mode 100644
index 00000000000..fe8a853f3af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c
@@ -0,0 +1,262 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-O3 --save-temps -Wno-pedantic" }  */
+#include <arm_neon.h>
+
+bfloat16_t glob_bfloat;
+bfloat16x4_t glob_bfloat_vec;
+
+float32x4_t is_a_float_vec;
+float32x2_t is_a_float_pair;
+
+float16x4_t *float_ptr;
+float16x4_t is_a_float16_vec;
+
+int32x4_t is_an_int_vec;
+int32x2_t is_an_int_pair;
+int16x4_t is_a_short_vec;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+double is_a_double;
+
+/* Create a vector of 2 bfloat16_t.  */
+typedef bfloat16_t v2bf __attribute__((vector_size(4)));
+v2bf foo1 (void) { return (v2bf) 0x12345678; }
+bfloat16x4_t foo2 (void) { return (bfloat16x4_t) 0x1234567812345678; }
+
+bfloat16x4_t footest (bfloat16x4_t vector0)
+{
+  /* Initialisation  */
+
+  bfloat16x4_t vector1_1;
+  bfloat16x4_t vector1_2 = glob_bfloat_vec;
+  bfloat16x4_t vector1_3 = is_a_float_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'float32x4_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector1_4 = is_an_int_vec;  /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'int32x4_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector1_5 = is_a_float16_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'float16x4_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector1_6 = is_a_float_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'float32x2_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector1_7 = is_an_int_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'int32x2_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector1_8 = is_a_short_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'int16x4_t'} "" {target *-*-*} } */
+
+  int32x4_t initi_1_1 = glob_bfloat_vec;   /* { dg-error {incompatible types when initializing type 'int32x4_t' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  float32x4_t initi_1_2 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float32x4_t' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  float16x4_t initi_1_3 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float16x4_t' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  float32x2_t initi_1_4 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float32x2_t' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  int32x2_t initi_1_5 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int32x2_t' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  int16x4_t initi_1_6 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int16x4_t' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+
+  bfloat16x4_t vector2_1 = {};
+  bfloat16x4_t vector2_2 = { glob_bfloat };
+  bfloat16x4_t vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
+  bfloat16x4_t vector2_4 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x4_t vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error "invalid conversion to type 'bfloat16_t'" "" {target *-*-*} } */
+
+  int32x4_t initi_2_1 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float32x4_t initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float16x4_t initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float32x2_t initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  int32x2_t initi_2_5 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  int16x4_t initi_2_6 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Assignments to/from vectors.  */
+
+  glob_bfloat_vec = glob_bfloat_vec;
+  glob_bfloat_vec = 0;   /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int'} "" {target *-*-*} } */
+  glob_bfloat_vec = 0.1; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'double'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_a_float_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'float32x4_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_an_int_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int32x4_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_a_float16_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'float16x4_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_a_float_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'float32x2_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_an_int_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int32x2_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_a_short_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int16x4_t'} "" {target *-*-*} } */
+
+  is_an_int_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int32x4_t' from type 'bfloat16x4_t'} "" {target *-*-*} } */
+  is_a_float_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float32x4_t' from type 'bfloat16x4_t'} "" {target *-*-*} } */
+  is_a_float16_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float16x4_t' from type 'bfloat16x4_t'} "" {target *-*-*} } */
+  is_a_float_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float32x2_t' from type 'bfloat16x4_t'} "" {target *-*-*} } */
+  is_an_int_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int32x2_t' from type 'bfloat16x4_t'} "" {target *-*-*} } */
+  is_a_short_vec = glob_bfloat_vec;/* { dg-error {incompatible types when assigning to type 'int16x4_t' from type 'bfloat16x4_t'} "" {target *-*-*} } */
+
+  /* Assignments to/from elements.  */
+
+  vector2_3[0] = glob_bfloat;
+  vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = 0; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+
+  glob_bfloat = vector2_3[0];
+  is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Compound literals.  */
+
+  (bfloat16x4_t) {};
+
+  (bfloat16x4_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16x4_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16x4_t) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float32x4_t'} "" {target *-*-*} } */
+  (bfloat16x4_t) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int32x4_t'} "" {target *-*-*} } */
+  (bfloat16x4_t) { is_a_float_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float32x2_t'} "" {target *-*-*} } */
+  (bfloat16x4_t) { is_an_int_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int32x2_t'} "" {target *-*-*} } */
+  (bfloat16x4_t) { is_a_float16_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float16x4_t'} "" {target *-*-*} } */
+  (bfloat16x4_t) { is_a_short_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int16x4_t'} "" {target *-*-*} } */
+
+  (bfloat16x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  (int32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'int' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  (float32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'float' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  (int32x2_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'int' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  (float16x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__fp16' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+  (int16x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'short int' using type 'bfloat16x4_t'} "" {target *-*-*} } */
+
+  /* Casting.  */
+
+  (void) glob_bfloat_vec;
+  (bfloat16x4_t) glob_bfloat_vec;
+
+  (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} "" {target *-*-*} } */
+  (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'short int' which has different size} "" {target *-*-*} } */
+  (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'int' which has different size} "" {target *-*-*} } */
+  (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} "" {target *-*-*} } */
+  (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} "" {target *-*-*} } */
+  (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} "" {target *-*-*} } */
+
+  (int32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__Int32x4_t' which has different size} "" {target *-*-*} } */
+  (float32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__Float32x4_t' which has different size} "" {target *-*-*} } */
+  (float16x4_t) glob_bfloat_vec;
+  (int32x2_t) glob_bfloat_vec;
+  (float32x2_t) glob_bfloat_vec;
+  (int16x4_t) glob_bfloat_vec;
+
+  (bfloat16x4_t) is_an_int_vec; /* { dg-error {cannot convert a value of type 'int32x4_t' to vector type '__Bfloat16x4_t' which has different size} "" {target *-*-*} } */
+  (bfloat16x4_t) is_a_float_vec; /* { dg-error {cannot convert a value of type 'float32x4_t' to vector type '__Bfloat16x4_t' which has different size} "" {target *-*-*} } */
+  (bfloat16x4_t) is_a_float16_vec;
+  (bfloat16x4_t) is_an_int_pair;
+  (bfloat16x4_t) is_a_float_pair;
+  (bfloat16x4_t) is_a_short_vec;
+  (bfloat16x4_t) is_a_double; /* { dg-error {cannot convert value to a vector} "" {target *-*-*} } */
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16x4_t array_type[2];
+  extern bfloat16x4_t extern_array[];
+
+  bfloat16x4_t array[2];
+  bfloat16x4_t zero_length_array[0];
+  bfloat16x4_t empty_init_array[] = {};
+  typedef bfloat16x4_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16x4_t a;
+  };
+
+  union union1 {
+    bfloat16x4_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16x4_t *bfloat_ptr = &vector0;
+  vector0 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16x4_t *bfloat_ptr2 = bfloat_ptr;
+  bfloat16x4_t *bfloat_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++bfloat_ptr;
+  --bfloat_ptr;
+  bfloat_ptr++;
+  bfloat_ptr--;
+  bfloat_ptr += 1;
+  bfloat_ptr -= 1;
+  bfloat_ptr - bfloat_ptr2;
+  bfloat_ptr = &bfloat_ptr3[0];
+  bfloat_ptr = &bfloat_ptr3[1];
+
+  /* Simple comparison.  */
+  vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_float_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 > 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  0 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 > 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  0.1 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  is_an_int_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Pointer comparison.  */
+
+  bfloat_ptr == &vector0;
+  bfloat_ptr != &vector0;
+  bfloat_ptr < &vector0;
+  bfloat_ptr <= &vector0;
+  bfloat_ptr > &vector0;
+  bfloat_ptr >= &vector0;
+  bfloat_ptr == bfloat_ptr2;
+  bfloat_ptr != bfloat_ptr2;
+  bfloat_ptr < bfloat_ptr2;
+  bfloat_ptr <= bfloat_ptr2;
+  bfloat_ptr > bfloat_ptr2;
+  bfloat_ptr >= bfloat_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? vector0 : vector0;
+  0 ? vector0 : is_a_float_vec; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? is_a_float_vec : vector0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? vector0 : is_a_float16_vec; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? is_a_float16_vec : vector0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? vector0 : 0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? 0 : vector0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? 0.1 : vector0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? vector0 : 0.1; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? bfloat_ptr : bfloat_ptr2;
+  0 ? bfloat_ptr : float_ptr; /* { dg-error {pointer type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? float_ptr : bfloat_ptr; /* { dg-error {pointer type mismatch in conditional expression} "" {target *-*-*} } */
+
+  vector0 ? vector0 : vector0; /* { dg-error {used vector type where scalar is required} "" {target *-*-*} } */
+  vector0 ? is_a_float16_vec : vector0; /* { dg-error {used vector type where scalar is required} "" {target *-*-*} } */
+  vector0 ? vector0 : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} "" {target *-*-*} } */
+  vector0 ? is_a_float16_vec : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} "" {target *-*-*} } */
+
+  /* Unary operators.  */
+
+  +vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  -vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  ~vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  !vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  *vector0; /* { dg-error {invalid type argument of unary '\*'} "" {target *-*-*} } */
+  __real vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  __imag vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  ++vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  --vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0++; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0--; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Binary arithmetic operations.  */
+
+  vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+
+  return vector0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c
new file mode 100644
index 00000000000..bd20e1bbc71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c
@@ -0,0 +1,260 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-O3 --save-temps -Wno-pedantic" }  */
+#include <arm_neon.h>
+
+bfloat16_t glob_bfloat;
+bfloat16x8_t glob_bfloat_vec;
+
+float32x4_t is_a_float_vec;
+float64x2_t is_a_double_pair;
+
+float16x8_t *float_ptr;
+float16x8_t is_a_float16_vec;
+
+int32x4_t is_an_int_vec;
+int64x2_t is_a_long_int_pair;
+int16x8_t is_a_short_vec;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+double is_a_double;
+
+bfloat16x8_t foo3 (void) { return (bfloat16x8_t) 0x12345678123456781234567812345678; }
+ /* { dg-error {integer constant is too large for its type} "" {target *-*-*} 27 } */
+ /* { dg-error {cannot convert a value of type 'long int' to vector type '__Bfloat16x8_t' which has different size} "" {target *-*-*} 27 } */
+
+bfloat16x8_t footest (bfloat16x8_t vector0)
+{
+  /* Initialisation  */
+
+  bfloat16x8_t vector1_1;
+  bfloat16x8_t vector1_2 = glob_bfloat_vec;
+  bfloat16x8_t vector1_3 = is_a_float_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'float32x4_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector1_4 = is_an_int_vec;  /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'int32x4_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector1_5 = is_a_float16_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'float16x8_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector1_6 = is_a_double_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'float64x2_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector1_7 = is_a_long_int_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'int64x2_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector1_8 = is_a_short_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'int16x8_t'} "" {target *-*-*} } */
+
+  int32x4_t initi_1_1 = glob_bfloat_vec;   /* { dg-error {incompatible types when initializing type 'int32x4_t' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  float32x4_t initi_1_2 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float32x4_t' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  float16x8_t initi_1_3 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float16x8_t' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  float64x2_t initi_1_4 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float64x2_t' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  int64x2_t initi_1_5 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int64x2_t' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  int16x8_t initi_1_6 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int16x8_t' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+
+  bfloat16x8_t vector2_1 = {};
+  bfloat16x8_t vector2_2 = { glob_bfloat };
+  bfloat16x8_t vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
+  bfloat16x8_t vector2_4 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  bfloat16x8_t vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error "invalid conversion to type 'bfloat16_t'" "" {target *-*-*} } */
+
+  int32x4_t initi_2_1 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float32x4_t initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float16x8_t initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  float64x2_t initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  int64x2_t initi_2_5 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  int16x8_t initi_2_6 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Assignments to/from vectors.  */
+
+  glob_bfloat_vec = glob_bfloat_vec;
+  glob_bfloat_vec = 0;   /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int'} "" {target *-*-*} } */
+  glob_bfloat_vec = 0.1; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'double'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_a_float_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'float32x4_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_an_int_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int32x4_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_a_float16_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'float16x8_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_a_double_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'float64x2_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_a_long_int_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int64x2_t'} "" {target *-*-*} } */
+  glob_bfloat_vec = is_a_short_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int16x8_t'} "" {target *-*-*} } */
+
+  is_an_int_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int32x4_t' from type 'bfloat16x8_t'} "" {target *-*-*} } */
+  is_a_float_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float32x4_t' from type 'bfloat16x8_t'} "" {target *-*-*} } */
+  is_a_float16_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float16x8_t' from type 'bfloat16x8_t'} "" {target *-*-*} } */
+  is_a_double_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float64x2_t' from type 'bfloat16x8_t'} "" {target *-*-*} } */
+  is_a_long_int_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int64x2_t' from type 'bfloat16x8_t'} "" {target *-*-*} } */
+  is_a_short_vec = glob_bfloat_vec;/* { dg-error {incompatible types when assigning to type 'int16x8_t' from type 'bfloat16x8_t'} "" {target *-*-*} } */
+
+  /* Assignments to/from elements.  */
+
+  vector2_3[0] = glob_bfloat;
+  vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = 0; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+
+  glob_bfloat = vector2_3[0];
+  is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Compound literals.  */
+
+  (bfloat16x8_t) {};
+
+  (bfloat16x8_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16x8_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
+  (bfloat16x8_t) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float32x4_t'} "" {target *-*-*} } */
+  (bfloat16x8_t) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int32x4_t'} "" {target *-*-*} } */
+  (bfloat16x8_t) { is_a_double_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float64x2_t'} "" {target *-*-*} } */
+  (bfloat16x8_t) { is_a_long_int_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int64x2_t'} "" {target *-*-*} } */
+  (bfloat16x8_t) { is_a_float16_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float16x8_t'} "" {target *-*-*} } */
+  (bfloat16x8_t) { is_a_short_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int16x8_t'} "" {target *-*-*} } */
+
+  (bfloat16x8_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  (int32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'int' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  (float32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'float' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  (int64x2_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'long int' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  (float16x8_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__fp16' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+  (int16x8_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'short int' using type 'bfloat16x8_t'} "" {target *-*-*} } */
+
+  /* Casting.  */
+
+  (void) glob_bfloat_vec;
+  (bfloat16x8_t) glob_bfloat_vec;
+
+  (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} "" {target *-*-*} } */
+  (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'short int' which has different size} "" {target *-*-*} } */
+  (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'int' which has different size} "" {target *-*-*} } */
+  (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} "" {target *-*-*} } */
+  (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} "" {target *-*-*} } */
+  (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} "" {target *-*-*} } */
+
+  (int32x4_t) glob_bfloat_vec; 
+  (float32x4_t) glob_bfloat_vec;
+  (float16x8_t) glob_bfloat_vec;
+  (int64x2_t) glob_bfloat_vec;
+  (float64x2_t) glob_bfloat_vec;
+  (int16x8_t) glob_bfloat_vec;
+
+  (bfloat16x8_t) is_an_int_vec;
+  (bfloat16x8_t) is_a_float_vec;
+  (bfloat16x8_t) is_a_float16_vec;
+  (bfloat16x8_t) is_a_long_int_pair;
+  (bfloat16x8_t) is_a_double_pair;
+  (bfloat16x8_t) is_a_short_vec;
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16x8_t array_type[2];
+  extern bfloat16x8_t extern_array[];
+
+  bfloat16x8_t array[2];
+  bfloat16x8_t zero_length_array[0];
+  bfloat16x8_t empty_init_array[] = {};
+  typedef bfloat16x8_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16x8_t a;
+  };
+
+  union union1 {
+    bfloat16x8_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16x8_t *bfloat_ptr = &vector0;
+  vector0 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16x8_t *bfloat_ptr2 = bfloat_ptr;
+  bfloat16x8_t *bfloat_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++bfloat_ptr;
+  --bfloat_ptr;
+  bfloat_ptr++;
+  bfloat_ptr--;
+  bfloat_ptr += 1;
+  bfloat_ptr -= 1;
+  bfloat_ptr - bfloat_ptr2;
+  bfloat_ptr = &bfloat_ptr3[0];
+  bfloat_ptr = &bfloat_ptr3[1];
+
+  /* Simple comparison.  */
+  vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  is_a_float_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 > 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  0 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 > 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  0.1 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  is_an_int_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Pointer comparison.  */
+
+  bfloat_ptr == &vector0;
+  bfloat_ptr != &vector0;
+  bfloat_ptr < &vector0;
+  bfloat_ptr <= &vector0;
+  bfloat_ptr > &vector0;
+  bfloat_ptr >= &vector0;
+  bfloat_ptr == bfloat_ptr2;
+  bfloat_ptr != bfloat_ptr2;
+  bfloat_ptr < bfloat_ptr2;
+  bfloat_ptr <= bfloat_ptr2;
+  bfloat_ptr > bfloat_ptr2;
+  bfloat_ptr >= bfloat_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? vector0 : vector0;
+  0 ? vector0 : is_a_float_vec; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? is_a_float_vec : vector0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? vector0 : is_a_float16_vec; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? is_a_float16_vec : vector0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? vector0 : 0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? 0 : vector0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? 0.1 : vector0; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? vector0 : 0.1; /* { dg-error {type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? bfloat_ptr : bfloat_ptr2;
+  0 ? bfloat_ptr : float_ptr; /* { dg-error {pointer type mismatch in conditional expression} "" {target *-*-*} } */
+  0 ? float_ptr : bfloat_ptr; /* { dg-error {pointer type mismatch in conditional expression} "" {target *-*-*} } */
+
+  vector0 ? vector0 : vector0; /* { dg-error {used vector type where scalar is required} "" {target *-*-*} } */
+  vector0 ? is_a_float16_vec : vector0; /* { dg-error {used vector type where scalar is required} "" {target *-*-*} } */
+  vector0 ? vector0 : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} "" {target *-*-*} } */
+  vector0 ? is_a_float16_vec : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} "" {target *-*-*} } */
+
+  /* Unary operators.  */
+
+  +vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  -vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  ~vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  !vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  *vector0; /* { dg-error {invalid type argument of unary '\*'} "" {target *-*-*} } */
+  __real vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  __imag vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  ++vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  --vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0++; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0--; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+
+  /* Binary arithmetic operations.  */
+
+  vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+  vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} "" {target *-*-*} } */
+
+  return vector0;
+}
+

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
  2020-01-09 15:03       ` Stam Markianos-Wright
@ 2020-01-09 16:13         ` Richard Sandiford
  2020-01-09 16:21           ` Stam Markianos-Wright
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Sandiford @ 2020-01-09 16:13 UTC (permalink / raw)
  To: Stam Markianos-Wright
  Cc: gcc-patches, Richard Earnshaw, Kyrylo Tkachov, Marcus Shawcroft

Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
> diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
> new file mode 100644
> index 00000000000..55cbb0b0ef7
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
> @@ -0,0 +1,14 @@
> +/* { dg-do assemble { target { aarch64*-*-* } } } */
> +/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
> +/* { dg-add-options arm_v8_2a_bf16_neon }  */
> +/* { dg-additional-options "-O3 --save-temps" } */
> +
> +#include <arm_neon.h>
> +
> +void foo (void)
> +{
> +  bfloat16_t (); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */

The "" {target *-*-*} stuff isn't needed: that's just for when the test
depends on a target selector or if you need to specify a line number
(which comes after the target).

Same for the rest of the patch.

> +  bfloat16_t a = bfloat16_t(); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */

Why's this one an error?  Looks like it should be OK.  Do we build
bfloat16_t() as a conversion from a zero integer?

Looks good otherwise, thanks, but I think we should try to support
the line above if we can.

Richard

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
  2020-01-09 16:13         ` Richard Sandiford
@ 2020-01-09 16:21           ` Stam Markianos-Wright
  2020-01-10 16:22             ` Stam Markianos-Wright
  0 siblings, 1 reply; 10+ messages in thread
From: Stam Markianos-Wright @ 2020-01-09 16:21 UTC (permalink / raw)
  To: gcc-patches, Richard Earnshaw, Kyrylo Tkachov, Marcus Shawcroft,
	Richard Sandiford



On 1/9/20 4:07 PM, Richard Sandiford wrote:
> Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
>> diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>> new file mode 100644
>> index 00000000000..55cbb0b0ef7
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>> @@ -0,0 +1,14 @@
>> +/* { dg-do assemble { target { aarch64*-*-* } } } */
>> +/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
>> +/* { dg-add-options arm_v8_2a_bf16_neon }  */
>> +/* { dg-additional-options "-O3 --save-temps" } */
>> +
>> +#include <arm_neon.h>
>> +
>> +void foo (void)
>> +{
>> +  bfloat16_t (); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
> 
> The "" {target *-*-*} stuff isn't needed: that's just for when the test
> depends on a target selector or if you need to specify a line number
> (which comes after the target).

Ah ok cool. I just had something that worked and was just doing ctrl+c ctrl+v 
everywhere!

> 
> Same for the rest of the patch.
> 
>> +  bfloat16_t a = bfloat16_t(); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" {target *-*-*} } */
> 
> Why's this one an error?  Looks like it should be OK.  Do we build
> bfloat16_t() as a conversion from a zero integer?
> 
Yea that's exactly what it looked like when I went into the debugging! But will 
investigate a bit further and see if I can fix it for the next revision.

Thank you so much for the help in getting these fixed :D

Cheers,
Stam

> Looks good otherwise, thanks, but I think we should try to support
> the line above if we can.
> 
> Richard
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
  2020-01-09 16:21           ` Stam Markianos-Wright
@ 2020-01-10 16:22             ` Stam Markianos-Wright
  2020-01-10 16:30               ` Richard Sandiford
  0 siblings, 1 reply; 10+ messages in thread
From: Stam Markianos-Wright @ 2020-01-10 16:22 UTC (permalink / raw)
  To: gcc-patches, Richard Earnshaw, Kyrylo Tkachov, Marcus Shawcroft,
	Richard Sandiford

[-- Attachment #1: Type: text/plain, Size: 1975 bytes --]



On 1/9/20 4:13 PM, Stam Markianos-Wright wrote:
> 
> 
> On 1/9/20 4:07 PM, Richard Sandiford wrote:
>> Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
>>> diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C 
>>> b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>>> new file mode 100644
>>> index 00000000000..55cbb0b0ef7
>>> --- /dev/null
>>> +++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>>> @@ -0,0 +1,14 @@
>>> +/* { dg-do assemble { target { aarch64*-*-* } } } */
>>> +/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
>>> +/* { dg-add-options arm_v8_2a_bf16_neon }  */
>>> +/* { dg-additional-options "-O3 --save-temps" } */
>>> +
>>> +#include <arm_neon.h>
>>> +
>>> +void foo (void)
>>> +{
>>> +  bfloat16_t (); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" 
>>> {target *-*-*} } */
>>
>> The "" {target *-*-*} stuff isn't needed: that's just for when the test
>> depends on a target selector or if you need to specify a line number
>> (which comes after the target).

Removed them.

> 
> Ah ok cool. I just had something that worked and was just doing ctrl+c ctrl+v 
> everywhere!
> 
>>
>> Same for the rest of the patch.
>>
>>> +  bfloat16_t a = bfloat16_t(); /* { dg-error {invalid conversion to type 
>>> 'bfloat16_t'} "" {target *-*-*} } */
>>
>> Why's this one an error?  Looks like it should be OK.  Do we build
>> bfloat16_t() as a conversion from a zero integer?
>>
> Yea that's exactly what it looked like when I went into the debugging! But will 
> investigate a bit further and see if I can fix it for the next revision.
> 

Changed this to dg-bogus with an XFAIL for the purposes of this patch in Stage 3 :)

> Thank you so much for the help in getting these fixed :D
> 
> Cheers,
> Stam
> 
>> Looks good otherwise, thanks, but I think we should try to support
>> the line above if we can.
>>
>> Richard
>>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: BFmode2of2.patch --]
[-- Type: text/x-patch; name="BFmode2of2.patch", Size: 48304 bytes --]

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index ebd3f6cf45bc0b5118c4c39e323e6380d64c885e..ce410ddf5515407a4680e186b04c6b6a40ae2562 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -21760,6 +21760,55 @@ aarch64_stack_protect_guard (void)
   return NULL_TREE;
 }
 
+/* Return the diagnostic message string if conversion from FROMTYPE to
+   TOTYPE is not allowed, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
+{
+  if (element_mode (fromtype) != element_mode (totype))
+    {
+      /* Do no allow conversions to/from BFmode scalar types.  */
+      if (TYPE_MODE (fromtype) == BFmode)
+	return N_("invalid conversion from type %<bfloat16_t%>");
+      if (TYPE_MODE (totype) == BFmode)
+	return N_("invalid conversion to type %<bfloat16_t%>");
+    }
+
+  /* Conversion allowed.  */
+  return NULL;
+}
+
+/* Return the diagnostic message string if the unary operation OP is
+   not permitted on TYPE, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_unary_op (int op, const_tree type)
+{
+  /* Reject all single-operand operations on BFmode except for &.  */
+  if (element_mode (type) == BFmode && op != ADDR_EXPR)
+    return N_("operation not permitted on type %<bfloat16_t%>");
+
+  /* Operation allowed.  */
+  return NULL;
+}
+
+/* Return the diagnostic message string if the binary operation OP is
+   not permitted on TYPE1 and TYPE2, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
+			   const_tree type2)
+{
+  /* Reject all 2-operand operations on BFmode.  */
+  if (element_mode (type1) == BFmode
+      || element_mode (type2) == BFmode)
+    return N_("operation not permitted on type %<bfloat16_t%>");
+
+  /* Operation allowed.  */
+  return NULL;
+}
+
 /* Implement TARGET_ASM_FILE_END for AArch64.  This adds the AArch64 GNU NOTE
    section at the end if needed.  */
 #define GNU_PROPERTY_AARCH64_FEATURE_1_AND	0xc0000000
@@ -22010,6 +22059,15 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE aarch64_mangle_type
 
+#undef TARGET_INVALID_CONVERSION
+#define TARGET_INVALID_CONVERSION aarch64_invalid_conversion
+
+#undef TARGET_INVALID_UNARY_OP
+#define TARGET_INVALID_UNARY_OP aarch64_invalid_unary_op
+
+#undef TARGET_INVALID_BINARY_OP
+#define TARGET_INVALID_BINARY_OP aarch64_invalid_binary_op
+
 #undef TARGET_VERIFY_TYPE_CONTEXT
 #define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context
 
diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
new file mode 100644
index 0000000000000000000000000000000000000000..0a04cfb18e567ae0eec88da8ea37922434c60080
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
@@ -0,0 +1,14 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-O3 --save-temps" } */
+
+#include <arm_neon.h>
+
+void foo (void)
+{
+  bfloat16_t (); /* { dg-bogus {invalid conversion to type 'bfloat16_t'} "" { xfail *-*-* } } */
+  bfloat16_t a = bfloat16_t(); /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t (0x1234); /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t (0.1); /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
new file mode 100644
index 0000000000000000000000000000000000000000..7c9188cf29da6587a678f280b672588777d2c030
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
@@ -0,0 +1,219 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-Wno-pedantic -O3 --save-temps" }  */
+
+#include <arm_neon.h>
+
+bfloat16_t glob_bfloat;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+double is_a_double;
+
+float *float_ptr;
+
+bfloat16_t foo1 (void) { return (bfloat16_t) 0x1234; } /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+bfloat16_t foo2 (void) { return (bfloat16_t) (short) 0x1234; } /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+bfloat16_t footest (bfloat16_t scalar0)
+{
+
+  /* Initialisation  */
+
+  bfloat16_t scalar1_1;
+  bfloat16_t scalar1_2 = glob_bfloat;
+  bfloat16_t scalar1_3 = 0;   /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_4 = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_5 = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_6 = is_an_int;  /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_8 = is_a_double; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float initi_1_2 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float16_t initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  short initi_1_4 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  double initi_1_5 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  bfloat16_t scalar2_1 = {}; /* { dg-error {empty scalar initializer} } */
+  bfloat16_t scalar2_2 = { glob_bfloat };
+  bfloat16_t scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_7 = { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float16_t initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  short initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  double initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Assignments.  */
+
+  glob_bfloat = glob_bfloat;
+  glob_bfloat = 0;   /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_double = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_short_int = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Casting.  */
+
+  (void) glob_bfloat;
+  (bfloat16_t) glob_bfloat;
+
+  (int) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (float) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (float16_t) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (double) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (short) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  (bfloat16_t) is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) is_a_double; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  /* Compound literals.  */
+
+  (bfloat16_t) {}; /* { dg-error {empty scalar initializer} } */
+  (bfloat16_t) { glob_bfloat };
+  (bfloat16_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_a_double }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  (int) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (float) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (float16_t) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (double) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (short) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16_t array_type[2];
+  extern bfloat16_t extern_array[];
+
+  bfloat16_t array[2];
+  bfloat16_t zero_length_array[0];
+  bfloat16_t empty_init_array[] = {};
+  typedef bfloat16_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16_t a;
+  };
+
+  union union1 {
+    bfloat16_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16_t *bfloat_ptr = &scalar0;
+  scalar0 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16_t *bfloat_ptr2 = bfloat_ptr;
+  bfloat16_t *bfloat_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++bfloat_ptr;
+  --bfloat_ptr;
+  bfloat_ptr++;
+  bfloat_ptr--;
+  bfloat_ptr += 1;
+  bfloat_ptr -= 1;
+  bfloat_ptr - bfloat_ptr2;
+  bfloat_ptr = &bfloat_ptr3[0];
+  bfloat_ptr = &bfloat_ptr3[1];
+
+  /* Simple comparison.  */
+  scalar0 > glob_bfloat; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  glob_bfloat == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 > is_a_float; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_a_float == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 > 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0 == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 > 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0.1 == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 > is_an_int; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_an_int == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Pointer comparison.  */
+
+  bfloat_ptr == &scalar0;
+  bfloat_ptr != &scalar0;
+  bfloat_ptr < &scalar0;
+  bfloat_ptr <= &scalar0;
+  bfloat_ptr > &scalar0;
+  bfloat_ptr >= &scalar0;
+  bfloat_ptr == bfloat_ptr2;
+  bfloat_ptr != bfloat_ptr2;
+  bfloat_ptr < bfloat_ptr2;
+  bfloat_ptr <= bfloat_ptr2;
+  bfloat_ptr > bfloat_ptr2;
+  bfloat_ptr >= bfloat_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? scalar0 : scalar0;
+  0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  0 ? scalar0 : 0; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  0 ? 0 : scalar0; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  0 ? bfloat_ptr : bfloat_ptr2;
+  0 ? bfloat_ptr : float_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+  0 ? float_ptr : bfloat_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+
+  scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 ? is_a_float : scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Unary operators.  */
+
+  +scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  -scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ~scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  !scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  *scalar0; /* { dg-error {invalid type argument of unary '\*'} } */
+  __real scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  __imag scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ++scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  --scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0++; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0--; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Binary arithmetic operations.  */
+
+  scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  return scalar0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..1a2aa9b3c1683edb0165dab565b135daf8403656
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c
@@ -0,0 +1,262 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-O3 --save-temps -Wno-pedantic" }  */
+#include <arm_neon.h>
+
+bfloat16_t glob_bfloat;
+bfloat16x4_t glob_bfloat_vec;
+
+float32x4_t is_a_float_vec;
+float32x2_t is_a_float_pair;
+
+float16x4_t *float_ptr;
+float16x4_t is_a_float16_vec;
+
+int32x4_t is_an_int_vec;
+int32x2_t is_an_int_pair;
+int16x4_t is_a_short_vec;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+double is_a_double;
+
+/* Create a vector of 2 bfloat16_t.  */
+typedef bfloat16_t v2bf __attribute__((vector_size(4)));
+v2bf foo1 (void) { return (v2bf) 0x12345678; }
+bfloat16x4_t foo2 (void) { return (bfloat16x4_t) 0x1234567812345678; }
+
+bfloat16x4_t footest (bfloat16x4_t vector0)
+{
+  /* Initialisation  */
+
+  bfloat16x4_t vector1_1;
+  bfloat16x4_t vector1_2 = glob_bfloat_vec;
+  bfloat16x4_t vector1_3 = is_a_float_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'float32x4_t'} } */
+  bfloat16x4_t vector1_4 = is_an_int_vec;  /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'int32x4_t'} } */
+  bfloat16x4_t vector1_5 = is_a_float16_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'float16x4_t'} } */
+  bfloat16x4_t vector1_6 = is_a_float_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'float32x2_t'} } */
+  bfloat16x4_t vector1_7 = is_an_int_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'int32x2_t'} } */
+  bfloat16x4_t vector1_8 = is_a_short_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'int16x4_t'} } */
+
+  int32x4_t initi_1_1 = glob_bfloat_vec;   /* { dg-error {incompatible types when initializing type 'int32x4_t' using type 'bfloat16x4_t'} } */
+  float32x4_t initi_1_2 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float32x4_t' using type 'bfloat16x4_t'} } */
+  float16x4_t initi_1_3 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float16x4_t' using type 'bfloat16x4_t'} } */
+  float32x2_t initi_1_4 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float32x2_t' using type 'bfloat16x4_t'} } */
+  int32x2_t initi_1_5 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int32x2_t' using type 'bfloat16x4_t'} } */
+  int16x4_t initi_1_6 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int16x4_t' using type 'bfloat16x4_t'} } */
+
+  bfloat16x4_t vector2_1 = {};
+  bfloat16x4_t vector2_2 = { glob_bfloat };
+  bfloat16x4_t vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
+  bfloat16x4_t vector2_4 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  int32x4_t initi_2_1 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float32x4_t initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float16x4_t initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float32x2_t initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  int32x2_t initi_2_5 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  int16x4_t initi_2_6 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Assignments to/from vectors.  */
+
+  glob_bfloat_vec = glob_bfloat_vec;
+  glob_bfloat_vec = 0;   /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int'} } */
+  glob_bfloat_vec = 0.1; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'double'} } */
+  glob_bfloat_vec = is_a_float_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'float32x4_t'} } */
+  glob_bfloat_vec = is_an_int_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int32x4_t'} } */
+  glob_bfloat_vec = is_a_float16_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'float16x4_t'} } */
+  glob_bfloat_vec = is_a_float_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'float32x2_t'} } */
+  glob_bfloat_vec = is_an_int_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int32x2_t'} } */
+  glob_bfloat_vec = is_a_short_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int16x4_t'} } */
+
+  is_an_int_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int32x4_t' from type 'bfloat16x4_t'} } */
+  is_a_float_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float32x4_t' from type 'bfloat16x4_t'} } */
+  is_a_float16_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float16x4_t' from type 'bfloat16x4_t'} } */
+  is_a_float_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float32x2_t' from type 'bfloat16x4_t'} } */
+  is_an_int_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int32x2_t' from type 'bfloat16x4_t'} } */
+  is_a_short_vec = glob_bfloat_vec;/* { dg-error {incompatible types when assigning to type 'int16x4_t' from type 'bfloat16x4_t'} } */
+
+  /* Assignments to/from elements.  */
+
+  vector2_3[0] = glob_bfloat;
+  vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = 0; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  glob_bfloat = vector2_3[0];
+  is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Compound literals.  */
+
+  (bfloat16x4_t) {};
+
+  (bfloat16x4_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16x4_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16x4_t) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float32x4_t'} } */
+  (bfloat16x4_t) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int32x4_t'} } */
+  (bfloat16x4_t) { is_a_float_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float32x2_t'} } */
+  (bfloat16x4_t) { is_an_int_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int32x2_t'} } */
+  (bfloat16x4_t) { is_a_float16_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float16x4_t'} } */
+  (bfloat16x4_t) { is_a_short_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int16x4_t'} } */
+
+  (bfloat16x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'bfloat16x4_t'} } */
+  (int32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'int' using type 'bfloat16x4_t'} } */
+  (float32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'float' using type 'bfloat16x4_t'} } */
+  (int32x2_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'int' using type 'bfloat16x4_t'} } */
+  (float16x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__fp16' using type 'bfloat16x4_t'} } */
+  (int16x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'short int' using type 'bfloat16x4_t'} } */
+
+  /* Casting.  */
+
+  (void) glob_bfloat_vec;
+  (bfloat16x4_t) glob_bfloat_vec;
+
+  (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'short int' which has different size} } */
+  (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'int' which has different size} } */
+  (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+
+  (int32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__Int32x4_t' which has different size} } */
+  (float32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__Float32x4_t' which has different size} } */
+  (float16x4_t) glob_bfloat_vec;
+  (int32x2_t) glob_bfloat_vec;
+  (float32x2_t) glob_bfloat_vec;
+  (int16x4_t) glob_bfloat_vec;
+
+  (bfloat16x4_t) is_an_int_vec; /* { dg-error {cannot convert a value of type 'int32x4_t' to vector type '__Bfloat16x4_t' which has different size} } */
+  (bfloat16x4_t) is_a_float_vec; /* { dg-error {cannot convert a value of type 'float32x4_t' to vector type '__Bfloat16x4_t' which has different size} } */
+  (bfloat16x4_t) is_a_float16_vec;
+  (bfloat16x4_t) is_an_int_pair;
+  (bfloat16x4_t) is_a_float_pair;
+  (bfloat16x4_t) is_a_short_vec;
+  (bfloat16x4_t) is_a_double; /* { dg-error {cannot convert value to a vector} } */
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16x4_t array_type[2];
+  extern bfloat16x4_t extern_array[];
+
+  bfloat16x4_t array[2];
+  bfloat16x4_t zero_length_array[0];
+  bfloat16x4_t empty_init_array[] = {};
+  typedef bfloat16x4_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16x4_t a;
+  };
+
+  union union1 {
+    bfloat16x4_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16x4_t *bfloat_ptr = &vector0;
+  vector0 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16x4_t *bfloat_ptr2 = bfloat_ptr;
+  bfloat16x4_t *bfloat_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++bfloat_ptr;
+  --bfloat_ptr;
+  bfloat_ptr++;
+  bfloat_ptr--;
+  bfloat_ptr += 1;
+  bfloat_ptr -= 1;
+  bfloat_ptr - bfloat_ptr2;
+  bfloat_ptr = &bfloat_ptr3[0];
+  bfloat_ptr = &bfloat_ptr3[1];
+
+  /* Simple comparison.  */
+  vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_a_float_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0.1 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_an_int_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Pointer comparison.  */
+
+  bfloat_ptr == &vector0;
+  bfloat_ptr != &vector0;
+  bfloat_ptr < &vector0;
+  bfloat_ptr <= &vector0;
+  bfloat_ptr > &vector0;
+  bfloat_ptr >= &vector0;
+  bfloat_ptr == bfloat_ptr2;
+  bfloat_ptr != bfloat_ptr2;
+  bfloat_ptr < bfloat_ptr2;
+  bfloat_ptr <= bfloat_ptr2;
+  bfloat_ptr > bfloat_ptr2;
+  bfloat_ptr >= bfloat_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? vector0 : vector0;
+  0 ? vector0 : is_a_float_vec; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? is_a_float_vec : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : is_a_float16_vec; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? is_a_float16_vec : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : 0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? 0 : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? 0.1 : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : 0.1; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? bfloat_ptr : bfloat_ptr2;
+  0 ? bfloat_ptr : float_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+  0 ? float_ptr : bfloat_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+
+  vector0 ? vector0 : vector0; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? is_a_float16_vec : vector0; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? vector0 : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? is_a_float16_vec : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} } */
+
+  /* Unary operators.  */
+
+  +vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  -vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ~vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  !vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  *vector0; /* { dg-error {invalid type argument of unary '\*'} } */
+  __real vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  __imag vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ++vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  --vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0++; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0--; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Binary arithmetic operations.  */
+
+  vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  return vector0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c
new file mode 100644
index 0000000000000000000000000000000000000000..586d05a928fbf3682b35e7de584e5d5a49dba196
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c
@@ -0,0 +1,260 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-O3 --save-temps -Wno-pedantic" }  */
+#include <arm_neon.h>
+
+bfloat16_t glob_bfloat;
+bfloat16x8_t glob_bfloat_vec;
+
+float32x4_t is_a_float_vec;
+float64x2_t is_a_double_pair;
+
+float16x8_t *float_ptr;
+float16x8_t is_a_float16_vec;
+
+int32x4_t is_an_int_vec;
+int64x2_t is_a_long_int_pair;
+int16x8_t is_a_short_vec;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+double is_a_double;
+
+bfloat16x8_t foo3 (void) { return (bfloat16x8_t) 0x12345678123456781234567812345678; }
+ /* { dg-error {integer constant is too large for its type} "" {target *-*-*} 27 } */
+ /* { dg-error {cannot convert a value of type 'long int' to vector type '__Bfloat16x8_t' which has different size} "" {target *-*-*} 27 } */
+
+bfloat16x8_t footest (bfloat16x8_t vector0)
+{
+  /* Initialisation  */
+
+  bfloat16x8_t vector1_1;
+  bfloat16x8_t vector1_2 = glob_bfloat_vec;
+  bfloat16x8_t vector1_3 = is_a_float_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'float32x4_t'} } */
+  bfloat16x8_t vector1_4 = is_an_int_vec;  /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'int32x4_t'} } */
+  bfloat16x8_t vector1_5 = is_a_float16_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'float16x8_t'} } */
+  bfloat16x8_t vector1_6 = is_a_double_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'float64x2_t'} } */
+  bfloat16x8_t vector1_7 = is_a_long_int_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'int64x2_t'} } */
+  bfloat16x8_t vector1_8 = is_a_short_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'int16x8_t'} } */
+
+  int32x4_t initi_1_1 = glob_bfloat_vec;   /* { dg-error {incompatible types when initializing type 'int32x4_t' using type 'bfloat16x8_t'} } */
+  float32x4_t initi_1_2 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float32x4_t' using type 'bfloat16x8_t'} } */
+  float16x8_t initi_1_3 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float16x8_t' using type 'bfloat16x8_t'} } */
+  float64x2_t initi_1_4 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float64x2_t' using type 'bfloat16x8_t'} } */
+  int64x2_t initi_1_5 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int64x2_t' using type 'bfloat16x8_t'} } */
+  int16x8_t initi_1_6 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int16x8_t' using type 'bfloat16x8_t'} } */
+
+  bfloat16x8_t vector2_1 = {};
+  bfloat16x8_t vector2_2 = { glob_bfloat };
+  bfloat16x8_t vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
+  bfloat16x8_t vector2_4 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error "invalid conversion to type 'bfloat16_t'" } */
+
+  int32x4_t initi_2_1 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float32x4_t initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float16x8_t initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float64x2_t initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  int64x2_t initi_2_5 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  int16x8_t initi_2_6 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Assignments to/from vectors.  */
+
+  glob_bfloat_vec = glob_bfloat_vec;
+  glob_bfloat_vec = 0;   /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int'} } */
+  glob_bfloat_vec = 0.1; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'double'} } */
+  glob_bfloat_vec = is_a_float_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'float32x4_t'} } */
+  glob_bfloat_vec = is_an_int_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int32x4_t'} } */
+  glob_bfloat_vec = is_a_float16_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'float16x8_t'} } */
+  glob_bfloat_vec = is_a_double_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'float64x2_t'} } */
+  glob_bfloat_vec = is_a_long_int_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int64x2_t'} } */
+  glob_bfloat_vec = is_a_short_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int16x8_t'} } */
+
+  is_an_int_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int32x4_t' from type 'bfloat16x8_t'} } */
+  is_a_float_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float32x4_t' from type 'bfloat16x8_t'} } */
+  is_a_float16_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float16x8_t' from type 'bfloat16x8_t'} } */
+  is_a_double_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float64x2_t' from type 'bfloat16x8_t'} } */
+  is_a_long_int_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int64x2_t' from type 'bfloat16x8_t'} } */
+  is_a_short_vec = glob_bfloat_vec;/* { dg-error {incompatible types when assigning to type 'int16x8_t' from type 'bfloat16x8_t'} } */
+
+  /* Assignments to/from elements.  */
+
+  vector2_3[0] = glob_bfloat;
+  vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = 0; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  glob_bfloat = vector2_3[0];
+  is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Compound literals.  */
+
+  (bfloat16x8_t) {};
+
+  (bfloat16x8_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16x8_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16x8_t) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float32x4_t'} } */
+  (bfloat16x8_t) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int32x4_t'} } */
+  (bfloat16x8_t) { is_a_double_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float64x2_t'} } */
+  (bfloat16x8_t) { is_a_long_int_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int64x2_t'} } */
+  (bfloat16x8_t) { is_a_float16_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float16x8_t'} } */
+  (bfloat16x8_t) { is_a_short_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int16x8_t'} } */
+
+  (bfloat16x8_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'bfloat16x8_t'} } */
+  (int32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'int' using type 'bfloat16x8_t'} } */
+  (float32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'float' using type 'bfloat16x8_t'} } */
+  (int64x2_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'long int' using type 'bfloat16x8_t'} } */
+  (float16x8_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__fp16' using type 'bfloat16x8_t'} } */
+  (int16x8_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'short int' using type 'bfloat16x8_t'} } */
+
+  /* Casting.  */
+
+  (void) glob_bfloat_vec;
+  (bfloat16x8_t) glob_bfloat_vec;
+
+  (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'short int' which has different size} } */
+  (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'int' which has different size} } */
+  (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+
+  (int32x4_t) glob_bfloat_vec;
+  (float32x4_t) glob_bfloat_vec;
+  (float16x8_t) glob_bfloat_vec;
+  (int64x2_t) glob_bfloat_vec;
+  (float64x2_t) glob_bfloat_vec;
+  (int16x8_t) glob_bfloat_vec;
+
+  (bfloat16x8_t) is_an_int_vec;
+  (bfloat16x8_t) is_a_float_vec;
+  (bfloat16x8_t) is_a_float16_vec;
+  (bfloat16x8_t) is_a_long_int_pair;
+  (bfloat16x8_t) is_a_double_pair;
+  (bfloat16x8_t) is_a_short_vec;
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16x8_t array_type[2];
+  extern bfloat16x8_t extern_array[];
+
+  bfloat16x8_t array[2];
+  bfloat16x8_t zero_length_array[0];
+  bfloat16x8_t empty_init_array[] = {};
+  typedef bfloat16x8_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16x8_t a;
+  };
+
+  union union1 {
+    bfloat16x8_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16x8_t *bfloat_ptr = &vector0;
+  vector0 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16x8_t *bfloat_ptr2 = bfloat_ptr;
+  bfloat16x8_t *bfloat_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++bfloat_ptr;
+  --bfloat_ptr;
+  bfloat_ptr++;
+  bfloat_ptr--;
+  bfloat_ptr += 1;
+  bfloat_ptr -= 1;
+  bfloat_ptr - bfloat_ptr2;
+  bfloat_ptr = &bfloat_ptr3[0];
+  bfloat_ptr = &bfloat_ptr3[1];
+
+  /* Simple comparison.  */
+  vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_a_float_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0.1 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_an_int_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Pointer comparison.  */
+
+  bfloat_ptr == &vector0;
+  bfloat_ptr != &vector0;
+  bfloat_ptr < &vector0;
+  bfloat_ptr <= &vector0;
+  bfloat_ptr > &vector0;
+  bfloat_ptr >= &vector0;
+  bfloat_ptr == bfloat_ptr2;
+  bfloat_ptr != bfloat_ptr2;
+  bfloat_ptr < bfloat_ptr2;
+  bfloat_ptr <= bfloat_ptr2;
+  bfloat_ptr > bfloat_ptr2;
+  bfloat_ptr >= bfloat_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? vector0 : vector0;
+  0 ? vector0 : is_a_float_vec; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? is_a_float_vec : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : is_a_float16_vec; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? is_a_float16_vec : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : 0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? 0 : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? 0.1 : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : 0.1; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? bfloat_ptr : bfloat_ptr2;
+  0 ? bfloat_ptr : float_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+  0 ? float_ptr : bfloat_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+
+  vector0 ? vector0 : vector0; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? is_a_float16_vec : vector0; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? vector0 : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? is_a_float16_vec : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} } */
+
+  /* Unary operators.  */
+
+  +vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  -vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ~vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  !vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  *vector0; /* { dg-error {invalid type argument of unary '\*'} } */
+  __real vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  __imag vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ++vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  --vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0++; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0--; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Binary arithmetic operations.  */
+
+  vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  return vector0;
+}
+

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
  2020-01-10 16:22             ` Stam Markianos-Wright
@ 2020-01-10 16:30               ` Richard Sandiford
  2020-01-10 20:13                 ` Stam Markianos-Wright
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Sandiford @ 2020-01-10 16:30 UTC (permalink / raw)
  To: Stam Markianos-Wright
  Cc: gcc-patches, Richard Earnshaw, Kyrylo Tkachov, Marcus Shawcroft

Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
> On 1/9/20 4:13 PM, Stam Markianos-Wright wrote:
>> On 1/9/20 4:07 PM, Richard Sandiford wrote:
>>> Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
>>>> diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C 
>>>> b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>>>> new file mode 100644
>>>> index 00000000000..55cbb0b0ef7
>>>> --- /dev/null
>>>> +++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>>>> @@ -0,0 +1,14 @@
>>>> +/* { dg-do assemble { target { aarch64*-*-* } } } */
>>>> +/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
>>>> +/* { dg-add-options arm_v8_2a_bf16_neon }  */
>>>> +/* { dg-additional-options "-O3 --save-temps" } */
>>>> +
>>>> +#include <arm_neon.h>
>>>> +
>>>> +void foo (void)
>>>> +{
>>>> +  bfloat16_t (); /* { dg-error {invalid conversion to type 'bfloat16_t'} "" 
>>>> {target *-*-*} } */
>>>
>>> The "" {target *-*-*} stuff isn't needed: that's just for when the test
>>> depends on a target selector or if you need to specify a line number
>>> (which comes after the target).
>
> Removed them.
>
>> 
>> Ah ok cool. I just had something that worked and was just doing ctrl+c ctrl+v 
>> everywhere!
>> 
>>>
>>> Same for the rest of the patch.
>>>
>>>> +  bfloat16_t a = bfloat16_t(); /* { dg-error {invalid conversion to type 
>>>> 'bfloat16_t'} "" {target *-*-*} } */
>>>
>>> Why's this one an error?  Looks like it should be OK.  Do we build
>>> bfloat16_t() as a conversion from a zero integer?
>>>
>> Yea that's exactly what it looked like when I went into the debugging! But will 
>> investigate a bit further and see if I can fix it for the next revision.
>> 
>
> Changed this to dg-bogus with an XFAIL for the purposes of this patch in Stage 3 :)

Yeah.  Like we discussed off-list, we'd need to change the target hook
to do this properly.  (And if we do change the target hook, it would be
good to make it output the errors itself, like we discussed upthread.)
Something for GCC 11 perhaps...

> diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
> new file mode 100644
> index 0000000000000000000000000000000000000000..0a04cfb18e567ae0eec88da8ea37922434c60080
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
> @@ -0,0 +1,14 @@
> +/* { dg-do assemble { target { aarch64*-*-* } } } */
> +/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
> +/* { dg-add-options arm_v8_2a_bf16_neon }  */
> +/* { dg-additional-options "-O3 --save-temps" } */
> +
> +#include <arm_neon.h>
> +
> +void foo (void)
> +{
> +  bfloat16_t (); /* { dg-bogus {invalid conversion to type 'bfloat16_t'} "" { xfail *-*-* } } */
> +  bfloat16_t a = bfloat16_t(); /* { dg-error {invalid conversion to type 'bfloat16_t'} } */

This should be a dg-bogus too.

OK with that change, thanks.

Richard

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2]
  2020-01-10 16:30               ` Richard Sandiford
@ 2020-01-10 20:13                 ` Stam Markianos-Wright
  0 siblings, 0 replies; 10+ messages in thread
From: Stam Markianos-Wright @ 2020-01-10 20:13 UTC (permalink / raw)
  To: gcc-patches, Richard Earnshaw, Kyrylo Tkachov, Marcus Shawcroft,
	Richard Sandiford

[-- Attachment #1: Type: text/plain, Size: 3264 bytes --]



On 1/10/20 4:29 PM, Richard Sandiford wrote:
> Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
>> On 1/9/20 4:13 PM, Stam Markianos-Wright wrote:
>>> On 1/9/20 4:07 PM, Richard Sandiford wrote:
>>>> Stam Markianos-Wright <Stam.Markianos-Wright@arm.com> writes:
>>>>> diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>>>>> b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>>>>> new file mode 100644
>>>>> index 00000000000..55cbb0b0ef7
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>>>>> @@ -0,0 +1,14 @@
>>>>> +/* { dg-do assemble { target { aarch64*-*-* } } } */
>>>>> +/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
>>>>> +/* { dg-add-options arm_v8_2a_bf16_neon }  */
>>>>> +/* { dg-additional-options "-O3 --save-temps" } */
>>>>> +
>>>>> +#include <arm_neon.h>
>>>>> +
>>>>> +void foo (void)
>>>>> +{
>>>>> +  bfloat16_t (); /* { dg-error {invalid conversion to type 'bfloat16_t'} ""
>>>>> {target *-*-*} } */
>>>>
>>>> The "" {target *-*-*} stuff isn't needed: that's just for when the test
>>>> depends on a target selector or if you need to specify a line number
>>>> (which comes after the target).
>>
>> Removed them.
>>
>>>
>>> Ah ok cool. I just had something that worked and was just doing ctrl+c ctrl+v
>>> everywhere!
>>>
>>>>
>>>> Same for the rest of the patch.
>>>>
>>>>> +  bfloat16_t a = bfloat16_t(); /* { dg-error {invalid conversion to type
>>>>> 'bfloat16_t'} "" {target *-*-*} } */
>>>>
>>>> Why's this one an error?  Looks like it should be OK.  Do we build
>>>> bfloat16_t() as a conversion from a zero integer?
>>>>
>>> Yea that's exactly what it looked like when I went into the debugging! But will
>>> investigate a bit further and see if I can fix it for the next revision.
>>>
>>
>> Changed this to dg-bogus with an XFAIL for the purposes of this patch in Stage 3 :)
> 
> Yeah.  Like we discussed off-list, we'd need to change the target hook
> to do this properly.  (And if we do change the target hook, it would be
> good to make it output the errors itself, like we discussed upthread.)
> Something for GCC 11 perhaps...

Agreed!

> 
>> diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..0a04cfb18e567ae0eec88da8ea37922434c60080
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
>> @@ -0,0 +1,14 @@
>> +/* { dg-do assemble { target { aarch64*-*-* } } } */
>> +/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
>> +/* { dg-add-options arm_v8_2a_bf16_neon }  */
>> +/* { dg-additional-options "-O3 --save-temps" } */
>> +
>> +#include <arm_neon.h>
>> +
>> +void foo (void)
>> +{
>> +  bfloat16_t (); /* { dg-bogus {invalid conversion to type 'bfloat16_t'} "" { xfail *-*-* } } */
>> +  bfloat16_t a = bfloat16_t(); /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
> 
> This should be a dg-bogus too.

Done and committed as 280130.

Diff attached for reference.

Cheers,
Stam

> 
> OK with that change, thanks.
> 
> Richard
> 


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: BFmode2of2-final.patch --]
[-- Type: text/x-patch; name="BFmode2of2-final.patch", Size: 48035 bytes --]

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index ebd3f6cf45b..ce410ddf551 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -21760,6 +21760,55 @@ aarch64_stack_protect_guard (void)
   return NULL_TREE;
 }
 
+/* Return the diagnostic message string if conversion from FROMTYPE to
+   TOTYPE is not allowed, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
+{
+  if (element_mode (fromtype) != element_mode (totype))
+    {
+      /* Do no allow conversions to/from BFmode scalar types.  */
+      if (TYPE_MODE (fromtype) == BFmode)
+	return N_("invalid conversion from type %<bfloat16_t%>");
+      if (TYPE_MODE (totype) == BFmode)
+	return N_("invalid conversion to type %<bfloat16_t%>");
+    }
+
+  /* Conversion allowed.  */
+  return NULL;
+}
+
+/* Return the diagnostic message string if the unary operation OP is
+   not permitted on TYPE, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_unary_op (int op, const_tree type)
+{
+  /* Reject all single-operand operations on BFmode except for &.  */
+  if (element_mode (type) == BFmode && op != ADDR_EXPR)
+    return N_("operation not permitted on type %<bfloat16_t%>");
+
+  /* Operation allowed.  */
+  return NULL;
+}
+
+/* Return the diagnostic message string if the binary operation OP is
+   not permitted on TYPE1 and TYPE2, NULL otherwise.  */
+
+static const char *
+aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
+			   const_tree type2)
+{
+  /* Reject all 2-operand operations on BFmode.  */
+  if (element_mode (type1) == BFmode
+      || element_mode (type2) == BFmode)
+    return N_("operation not permitted on type %<bfloat16_t%>");
+
+  /* Operation allowed.  */
+  return NULL;
+}
+
 /* Implement TARGET_ASM_FILE_END for AArch64.  This adds the AArch64 GNU NOTE
    section at the end if needed.  */
 #define GNU_PROPERTY_AARCH64_FEATURE_1_AND	0xc0000000
@@ -22010,6 +22059,15 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE aarch64_mangle_type
 
+#undef TARGET_INVALID_CONVERSION
+#define TARGET_INVALID_CONVERSION aarch64_invalid_conversion
+
+#undef TARGET_INVALID_UNARY_OP
+#define TARGET_INVALID_UNARY_OP aarch64_invalid_unary_op
+
+#undef TARGET_INVALID_BINARY_OP
+#define TARGET_INVALID_BINARY_OP aarch64_invalid_binary_op
+
 #undef TARGET_VERIFY_TYPE_CONTEXT
 #define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context
 
diff --git a/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
new file mode 100644
index 00000000000..9203d91f8ff
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/bfloat_cpp_typecheck.C
@@ -0,0 +1,14 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-O3 --save-temps" } */
+
+#include <arm_neon.h>
+
+void foo (void)
+{
+  bfloat16_t (); /* { dg-bogus {invalid conversion to type 'bfloat16_t'} "" { xfail *-*-* } } */
+  bfloat16_t a = bfloat16_t(); /* { dg-bogus {invalid conversion to type 'bfloat16_t'} "" { xfail *-*-* } } */
+  bfloat16_t (0x1234); /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t (0.1); /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
new file mode 100644
index 00000000000..7c9188cf29d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
@@ -0,0 +1,219 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-Wno-pedantic -O3 --save-temps" }  */
+
+#include <arm_neon.h>
+
+bfloat16_t glob_bfloat;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+double is_a_double;
+
+float *float_ptr;
+
+bfloat16_t foo1 (void) { return (bfloat16_t) 0x1234; } /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+bfloat16_t foo2 (void) { return (bfloat16_t) (short) 0x1234; } /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+bfloat16_t footest (bfloat16_t scalar0)
+{
+
+  /* Initialisation  */
+
+  bfloat16_t scalar1_1;
+  bfloat16_t scalar1_2 = glob_bfloat;
+  bfloat16_t scalar1_3 = 0;   /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_4 = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_5 = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_6 = is_an_int;  /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_8 = is_a_double; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float initi_1_2 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float16_t initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  short initi_1_4 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  double initi_1_5 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  bfloat16_t scalar2_1 = {}; /* { dg-error {empty scalar initializer} } */
+  bfloat16_t scalar2_2 = { glob_bfloat };
+  bfloat16_t scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_7 = { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16_t scalar2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float16_t initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  short initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  double initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Assignments.  */
+
+  glob_bfloat = glob_bfloat;
+  glob_bfloat = 0;   /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  glob_bfloat = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_double = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_short_int = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Casting.  */
+
+  (void) glob_bfloat;
+  (bfloat16_t) glob_bfloat;
+
+  (int) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (float) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (float16_t) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (double) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (short) glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  (bfloat16_t) is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) is_a_double; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  /* Compound literals.  */
+
+  (bfloat16_t) {}; /* { dg-error {empty scalar initializer} } */
+  (bfloat16_t) { glob_bfloat };
+  (bfloat16_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_a_double }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16_t) { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  (int) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (float) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (float16_t) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (double) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  (short) { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16_t array_type[2];
+  extern bfloat16_t extern_array[];
+
+  bfloat16_t array[2];
+  bfloat16_t zero_length_array[0];
+  bfloat16_t empty_init_array[] = {};
+  typedef bfloat16_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16_t a;
+  };
+
+  union union1 {
+    bfloat16_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16_t *bfloat_ptr = &scalar0;
+  scalar0 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16_t *bfloat_ptr2 = bfloat_ptr;
+  bfloat16_t *bfloat_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++bfloat_ptr;
+  --bfloat_ptr;
+  bfloat_ptr++;
+  bfloat_ptr--;
+  bfloat_ptr += 1;
+  bfloat_ptr -= 1;
+  bfloat_ptr - bfloat_ptr2;
+  bfloat_ptr = &bfloat_ptr3[0];
+  bfloat_ptr = &bfloat_ptr3[1];
+
+  /* Simple comparison.  */
+  scalar0 > glob_bfloat; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  glob_bfloat == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 > is_a_float; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_a_float == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 > 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0 == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 > 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0.1 == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 > is_an_int; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_an_int == scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Pointer comparison.  */
+
+  bfloat_ptr == &scalar0;
+  bfloat_ptr != &scalar0;
+  bfloat_ptr < &scalar0;
+  bfloat_ptr <= &scalar0;
+  bfloat_ptr > &scalar0;
+  bfloat_ptr >= &scalar0;
+  bfloat_ptr == bfloat_ptr2;
+  bfloat_ptr != bfloat_ptr2;
+  bfloat_ptr < bfloat_ptr2;
+  bfloat_ptr <= bfloat_ptr2;
+  bfloat_ptr > bfloat_ptr2;
+  bfloat_ptr >= bfloat_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? scalar0 : scalar0;
+  0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  0 ? scalar0 : 0; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  0 ? 0 : scalar0; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  0 ? bfloat_ptr : bfloat_ptr2;
+  0 ? bfloat_ptr : float_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+  0 ? float_ptr : bfloat_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+
+  scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 ? is_a_float : scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Unary operators.  */
+
+  +scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  -scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ~scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  !scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  *scalar0; /* { dg-error {invalid type argument of unary '\*'} } */
+  __real scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  __imag scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ++scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  --scalar0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0++; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0--; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Binary arithmetic operations.  */
+
+  scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  return scalar0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c
new file mode 100644
index 00000000000..1a2aa9b3c16
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c
@@ -0,0 +1,262 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-O3 --save-temps -Wno-pedantic" }  */
+#include <arm_neon.h>
+
+bfloat16_t glob_bfloat;
+bfloat16x4_t glob_bfloat_vec;
+
+float32x4_t is_a_float_vec;
+float32x2_t is_a_float_pair;
+
+float16x4_t *float_ptr;
+float16x4_t is_a_float16_vec;
+
+int32x4_t is_an_int_vec;
+int32x2_t is_an_int_pair;
+int16x4_t is_a_short_vec;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+double is_a_double;
+
+/* Create a vector of 2 bfloat16_t.  */
+typedef bfloat16_t v2bf __attribute__((vector_size(4)));
+v2bf foo1 (void) { return (v2bf) 0x12345678; }
+bfloat16x4_t foo2 (void) { return (bfloat16x4_t) 0x1234567812345678; }
+
+bfloat16x4_t footest (bfloat16x4_t vector0)
+{
+  /* Initialisation  */
+
+  bfloat16x4_t vector1_1;
+  bfloat16x4_t vector1_2 = glob_bfloat_vec;
+  bfloat16x4_t vector1_3 = is_a_float_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'float32x4_t'} } */
+  bfloat16x4_t vector1_4 = is_an_int_vec;  /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'int32x4_t'} } */
+  bfloat16x4_t vector1_5 = is_a_float16_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'float16x4_t'} } */
+  bfloat16x4_t vector1_6 = is_a_float_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'float32x2_t'} } */
+  bfloat16x4_t vector1_7 = is_an_int_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'int32x2_t'} } */
+  bfloat16x4_t vector1_8 = is_a_short_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x4_t' using type 'int16x4_t'} } */
+
+  int32x4_t initi_1_1 = glob_bfloat_vec;   /* { dg-error {incompatible types when initializing type 'int32x4_t' using type 'bfloat16x4_t'} } */
+  float32x4_t initi_1_2 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float32x4_t' using type 'bfloat16x4_t'} } */
+  float16x4_t initi_1_3 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float16x4_t' using type 'bfloat16x4_t'} } */
+  float32x2_t initi_1_4 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float32x2_t' using type 'bfloat16x4_t'} } */
+  int32x2_t initi_1_5 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int32x2_t' using type 'bfloat16x4_t'} } */
+  int16x4_t initi_1_6 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int16x4_t' using type 'bfloat16x4_t'} } */
+
+  bfloat16x4_t vector2_1 = {};
+  bfloat16x4_t vector2_2 = { glob_bfloat };
+  bfloat16x4_t vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
+  bfloat16x4_t vector2_4 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x4_t vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  int32x4_t initi_2_1 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float32x4_t initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float16x4_t initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float32x2_t initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  int32x2_t initi_2_5 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  int16x4_t initi_2_6 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Assignments to/from vectors.  */
+
+  glob_bfloat_vec = glob_bfloat_vec;
+  glob_bfloat_vec = 0;   /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int'} } */
+  glob_bfloat_vec = 0.1; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'double'} } */
+  glob_bfloat_vec = is_a_float_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'float32x4_t'} } */
+  glob_bfloat_vec = is_an_int_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int32x4_t'} } */
+  glob_bfloat_vec = is_a_float16_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'float16x4_t'} } */
+  glob_bfloat_vec = is_a_float_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'float32x2_t'} } */
+  glob_bfloat_vec = is_an_int_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int32x2_t'} } */
+  glob_bfloat_vec = is_a_short_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x4_t' from type 'int16x4_t'} } */
+
+  is_an_int_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int32x4_t' from type 'bfloat16x4_t'} } */
+  is_a_float_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float32x4_t' from type 'bfloat16x4_t'} } */
+  is_a_float16_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float16x4_t' from type 'bfloat16x4_t'} } */
+  is_a_float_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float32x2_t' from type 'bfloat16x4_t'} } */
+  is_an_int_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int32x2_t' from type 'bfloat16x4_t'} } */
+  is_a_short_vec = glob_bfloat_vec;/* { dg-error {incompatible types when assigning to type 'int16x4_t' from type 'bfloat16x4_t'} } */
+
+  /* Assignments to/from elements.  */
+
+  vector2_3[0] = glob_bfloat;
+  vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = 0; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  glob_bfloat = vector2_3[0];
+  is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Compound literals.  */
+
+  (bfloat16x4_t) {};
+
+  (bfloat16x4_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16x4_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16x4_t) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float32x4_t'} } */
+  (bfloat16x4_t) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int32x4_t'} } */
+  (bfloat16x4_t) { is_a_float_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float32x2_t'} } */
+  (bfloat16x4_t) { is_an_int_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int32x2_t'} } */
+  (bfloat16x4_t) { is_a_float16_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float16x4_t'} } */
+  (bfloat16x4_t) { is_a_short_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int16x4_t'} } */
+
+  (bfloat16x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'bfloat16x4_t'} } */
+  (int32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'int' using type 'bfloat16x4_t'} } */
+  (float32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'float' using type 'bfloat16x4_t'} } */
+  (int32x2_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'int' using type 'bfloat16x4_t'} } */
+  (float16x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__fp16' using type 'bfloat16x4_t'} } */
+  (int16x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'short int' using type 'bfloat16x4_t'} } */
+
+  /* Casting.  */
+
+  (void) glob_bfloat_vec;
+  (bfloat16x4_t) glob_bfloat_vec;
+
+  (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'short int' which has different size} } */
+  (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'int' which has different size} } */
+  (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+
+  (int32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__Int32x4_t' which has different size} } */
+  (float32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__Float32x4_t' which has different size} } */
+  (float16x4_t) glob_bfloat_vec;
+  (int32x2_t) glob_bfloat_vec;
+  (float32x2_t) glob_bfloat_vec;
+  (int16x4_t) glob_bfloat_vec;
+
+  (bfloat16x4_t) is_an_int_vec; /* { dg-error {cannot convert a value of type 'int32x4_t' to vector type '__Bfloat16x4_t' which has different size} } */
+  (bfloat16x4_t) is_a_float_vec; /* { dg-error {cannot convert a value of type 'float32x4_t' to vector type '__Bfloat16x4_t' which has different size} } */
+  (bfloat16x4_t) is_a_float16_vec;
+  (bfloat16x4_t) is_an_int_pair;
+  (bfloat16x4_t) is_a_float_pair;
+  (bfloat16x4_t) is_a_short_vec;
+  (bfloat16x4_t) is_a_double; /* { dg-error {cannot convert value to a vector} } */
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16x4_t array_type[2];
+  extern bfloat16x4_t extern_array[];
+
+  bfloat16x4_t array[2];
+  bfloat16x4_t zero_length_array[0];
+  bfloat16x4_t empty_init_array[] = {};
+  typedef bfloat16x4_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16x4_t a;
+  };
+
+  union union1 {
+    bfloat16x4_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16x4_t *bfloat_ptr = &vector0;
+  vector0 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16x4_t *bfloat_ptr2 = bfloat_ptr;
+  bfloat16x4_t *bfloat_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++bfloat_ptr;
+  --bfloat_ptr;
+  bfloat_ptr++;
+  bfloat_ptr--;
+  bfloat_ptr += 1;
+  bfloat_ptr -= 1;
+  bfloat_ptr - bfloat_ptr2;
+  bfloat_ptr = &bfloat_ptr3[0];
+  bfloat_ptr = &bfloat_ptr3[1];
+
+  /* Simple comparison.  */
+  vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_a_float_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0.1 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_an_int_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Pointer comparison.  */
+
+  bfloat_ptr == &vector0;
+  bfloat_ptr != &vector0;
+  bfloat_ptr < &vector0;
+  bfloat_ptr <= &vector0;
+  bfloat_ptr > &vector0;
+  bfloat_ptr >= &vector0;
+  bfloat_ptr == bfloat_ptr2;
+  bfloat_ptr != bfloat_ptr2;
+  bfloat_ptr < bfloat_ptr2;
+  bfloat_ptr <= bfloat_ptr2;
+  bfloat_ptr > bfloat_ptr2;
+  bfloat_ptr >= bfloat_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? vector0 : vector0;
+  0 ? vector0 : is_a_float_vec; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? is_a_float_vec : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : is_a_float16_vec; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? is_a_float16_vec : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : 0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? 0 : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? 0.1 : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : 0.1; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? bfloat_ptr : bfloat_ptr2;
+  0 ? bfloat_ptr : float_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+  0 ? float_ptr : bfloat_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+
+  vector0 ? vector0 : vector0; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? is_a_float16_vec : vector0; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? vector0 : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? is_a_float16_vec : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} } */
+
+  /* Unary operators.  */
+
+  +vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  -vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ~vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  !vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  *vector0; /* { dg-error {invalid type argument of unary '\*'} } */
+  __real vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  __imag vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ++vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  --vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0++; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0--; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Binary arithmetic operations.  */
+
+  vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  return vector0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c
new file mode 100644
index 00000000000..586d05a928f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c
@@ -0,0 +1,260 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon }  */
+/* { dg-additional-options "-O3 --save-temps -Wno-pedantic" }  */
+#include <arm_neon.h>
+
+bfloat16_t glob_bfloat;
+bfloat16x8_t glob_bfloat_vec;
+
+float32x4_t is_a_float_vec;
+float64x2_t is_a_double_pair;
+
+float16x8_t *float_ptr;
+float16x8_t is_a_float16_vec;
+
+int32x4_t is_an_int_vec;
+int64x2_t is_a_long_int_pair;
+int16x8_t is_a_short_vec;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+double is_a_double;
+
+bfloat16x8_t foo3 (void) { return (bfloat16x8_t) 0x12345678123456781234567812345678; }
+ /* { dg-error {integer constant is too large for its type} "" {target *-*-*} 27 } */
+ /* { dg-error {cannot convert a value of type 'long int' to vector type '__Bfloat16x8_t' which has different size} "" {target *-*-*} 27 } */
+
+bfloat16x8_t footest (bfloat16x8_t vector0)
+{
+  /* Initialisation  */
+
+  bfloat16x8_t vector1_1;
+  bfloat16x8_t vector1_2 = glob_bfloat_vec;
+  bfloat16x8_t vector1_3 = is_a_float_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'float32x4_t'} } */
+  bfloat16x8_t vector1_4 = is_an_int_vec;  /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'int32x4_t'} } */
+  bfloat16x8_t vector1_5 = is_a_float16_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'float16x8_t'} } */
+  bfloat16x8_t vector1_6 = is_a_double_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'float64x2_t'} } */
+  bfloat16x8_t vector1_7 = is_a_long_int_pair; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'int64x2_t'} } */
+  bfloat16x8_t vector1_8 = is_a_short_vec; /* { dg-error {incompatible types when initializing type 'bfloat16x8_t' using type 'int16x8_t'} } */
+
+  int32x4_t initi_1_1 = glob_bfloat_vec;   /* { dg-error {incompatible types when initializing type 'int32x4_t' using type 'bfloat16x8_t'} } */
+  float32x4_t initi_1_2 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float32x4_t' using type 'bfloat16x8_t'} } */
+  float16x8_t initi_1_3 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float16x8_t' using type 'bfloat16x8_t'} } */
+  float64x2_t initi_1_4 = glob_bfloat_vec; /* { dg-error {incompatible types when initializing type 'float64x2_t' using type 'bfloat16x8_t'} } */
+  int64x2_t initi_1_5 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int64x2_t' using type 'bfloat16x8_t'} } */
+  int16x8_t initi_1_6 = glob_bfloat_vec;  /* { dg-error {incompatible types when initializing type 'int16x8_t' using type 'bfloat16x8_t'} } */
+
+  bfloat16x8_t vector2_1 = {};
+  bfloat16x8_t vector2_2 = { glob_bfloat };
+  bfloat16x8_t vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
+  bfloat16x8_t vector2_4 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  bfloat16x8_t vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error "invalid conversion to type 'bfloat16_t'" } */
+
+  int32x4_t initi_2_1 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float32x4_t initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float16x8_t initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  float64x2_t initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  int64x2_t initi_2_5 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  int16x8_t initi_2_6 = { glob_bfloat };   /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Assignments to/from vectors.  */
+
+  glob_bfloat_vec = glob_bfloat_vec;
+  glob_bfloat_vec = 0;   /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int'} } */
+  glob_bfloat_vec = 0.1; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'double'} } */
+  glob_bfloat_vec = is_a_float_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'float32x4_t'} } */
+  glob_bfloat_vec = is_an_int_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int32x4_t'} } */
+  glob_bfloat_vec = is_a_float16_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'float16x8_t'} } */
+  glob_bfloat_vec = is_a_double_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'float64x2_t'} } */
+  glob_bfloat_vec = is_a_long_int_pair; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int64x2_t'} } */
+  glob_bfloat_vec = is_a_short_vec; /* { dg-error {incompatible types when assigning to type 'bfloat16x8_t' from type 'int16x8_t'} } */
+
+  is_an_int_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int32x4_t' from type 'bfloat16x8_t'} } */
+  is_a_float_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float32x4_t' from type 'bfloat16x8_t'} } */
+  is_a_float16_vec = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float16x8_t' from type 'bfloat16x8_t'} } */
+  is_a_double_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'float64x2_t' from type 'bfloat16x8_t'} } */
+  is_a_long_int_pair = glob_bfloat_vec; /* { dg-error {incompatible types when assigning to type 'int64x2_t' from type 'bfloat16x8_t'} } */
+  is_a_short_vec = glob_bfloat_vec;/* { dg-error {incompatible types when assigning to type 'int16x8_t' from type 'bfloat16x8_t'} } */
+
+  /* Assignments to/from elements.  */
+
+  vector2_3[0] = glob_bfloat;
+  vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = 0; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+
+  glob_bfloat = vector2_3[0];
+  is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+  is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+
+  /* Compound literals.  */
+
+  (bfloat16x8_t) {};
+
+  (bfloat16x8_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16x8_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+  (bfloat16x8_t) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float32x4_t'} } */
+  (bfloat16x8_t) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int32x4_t'} } */
+  (bfloat16x8_t) { is_a_double_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float64x2_t'} } */
+  (bfloat16x8_t) { is_a_long_int_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int64x2_t'} } */
+  (bfloat16x8_t) { is_a_float16_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'float16x8_t'} } */
+  (bfloat16x8_t) { is_a_short_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'int16x8_t'} } */
+
+  (bfloat16x8_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type 'bfloat16x8_t'} } */
+  (int32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'int' using type 'bfloat16x8_t'} } */
+  (float32x4_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'float' using type 'bfloat16x8_t'} } */
+  (int64x2_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'long int' using type 'bfloat16x8_t'} } */
+  (float16x8_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type '__fp16' using type 'bfloat16x8_t'} } */
+  (int16x8_t) { glob_bfloat_vec }; /* { dg-error {incompatible types when initializing type 'short int' using type 'bfloat16x8_t'} } */
+
+  /* Casting.  */
+
+  (void) glob_bfloat_vec;
+  (bfloat16x8_t) glob_bfloat_vec;
+
+  (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'short int' which has different size} } */
+  (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'int' which has different size} } */
+  (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+  (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */
+
+  (int32x4_t) glob_bfloat_vec;
+  (float32x4_t) glob_bfloat_vec;
+  (float16x8_t) glob_bfloat_vec;
+  (int64x2_t) glob_bfloat_vec;
+  (float64x2_t) glob_bfloat_vec;
+  (int16x8_t) glob_bfloat_vec;
+
+  (bfloat16x8_t) is_an_int_vec;
+  (bfloat16x8_t) is_a_float_vec;
+  (bfloat16x8_t) is_a_float16_vec;
+  (bfloat16x8_t) is_a_long_int_pair;
+  (bfloat16x8_t) is_a_double_pair;
+  (bfloat16x8_t) is_a_short_vec;
+
+  /* Arrays and Structs.  */
+
+  typedef bfloat16x8_t array_type[2];
+  extern bfloat16x8_t extern_array[];
+
+  bfloat16x8_t array[2];
+  bfloat16x8_t zero_length_array[0];
+  bfloat16x8_t empty_init_array[] = {};
+  typedef bfloat16x8_t some_other_type[is_an_int];
+
+  struct struct1 {
+    bfloat16x8_t a;
+  };
+
+  union union1 {
+    bfloat16x8_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  bfloat16x8_t *bfloat_ptr = &vector0;
+  vector0 = *bfloat_ptr;
+
+  /* Pointer assignment.  */
+
+  bfloat16x8_t *bfloat_ptr2 = bfloat_ptr;
+  bfloat16x8_t *bfloat_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++bfloat_ptr;
+  --bfloat_ptr;
+  bfloat_ptr++;
+  bfloat_ptr--;
+  bfloat_ptr += 1;
+  bfloat_ptr -= 1;
+  bfloat_ptr - bfloat_ptr2;
+  bfloat_ptr = &bfloat_ptr3[0];
+  bfloat_ptr = &bfloat_ptr3[1];
+
+  /* Simple comparison.  */
+  vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_a_float_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  0.1 == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  is_an_int_vec == vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Pointer comparison.  */
+
+  bfloat_ptr == &vector0;
+  bfloat_ptr != &vector0;
+  bfloat_ptr < &vector0;
+  bfloat_ptr <= &vector0;
+  bfloat_ptr > &vector0;
+  bfloat_ptr >= &vector0;
+  bfloat_ptr == bfloat_ptr2;
+  bfloat_ptr != bfloat_ptr2;
+  bfloat_ptr < bfloat_ptr2;
+  bfloat_ptr <= bfloat_ptr2;
+  bfloat_ptr > bfloat_ptr2;
+  bfloat_ptr >= bfloat_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? vector0 : vector0;
+  0 ? vector0 : is_a_float_vec; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? is_a_float_vec : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : is_a_float16_vec; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? is_a_float16_vec : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : 0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? 0 : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? 0.1 : vector0; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? vector0 : 0.1; /* { dg-error {type mismatch in conditional expression} } */
+  0 ? bfloat_ptr : bfloat_ptr2;
+  0 ? bfloat_ptr : float_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+  0 ? float_ptr : bfloat_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+
+  vector0 ? vector0 : vector0; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? is_a_float16_vec : vector0; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? vector0 : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} } */
+  vector0 ? is_a_float16_vec : is_a_float16_vec; /* { dg-error {used vector type where scalar is required} } */
+
+  /* Unary operators.  */
+
+  +vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  -vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ~vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  !vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  *vector0; /* { dg-error {invalid type argument of unary '\*'} } */
+  __real vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  __imag vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  ++vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  --vector0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0++; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0--; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  /* Binary arithmetic operations.  */
+
+  vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+  vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type 'bfloat16_t'} } */
+
+  return vector0;
+}
+


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-01-10 19:31 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-18 16:40 [GCC][PATCH][Aarch64] Add Bfloat16_t scalar type, vector types and machine modes to Aarch64 back-end [2/2] Stam Markianos-Wright
2019-12-19 10:10 ` Richard Sandiford
2020-01-07 11:42   ` Stam Markianos-Wright
2020-01-07 15:26     ` Richard Sandiford
2020-01-09 15:03       ` Stam Markianos-Wright
2020-01-09 16:13         ` Richard Sandiford
2020-01-09 16:21           ` Stam Markianos-Wright
2020-01-10 16:22             ` Stam Markianos-Wright
2020-01-10 16:30               ` Richard Sandiford
2020-01-10 20:13                 ` Stam Markianos-Wright

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).