The ACLE defines a new scalar type, __mfp8. This is an opaque 8bit types that
can only be used by fp8 intrinsics. Additionally, the mfloat8_t type is made
available in arm_neon.h and arm_sve.h as an alias of the same.

This implementation uses an INTEGER_TYPE, with precision 8 to represent
__mfp8. Conversions to int and other types are disabled via the
TARGET_INVALID_CONVERSION hook.
Additionally, operations that are typically available to integer types are
disabled via TARGET_INVALID_UNARY_OP and TARGET_INVALID_BINARY_OP hooks.

gcc/ChangeLog:

        * config/aarch64/aarch64-builtins.cc (aarch64_mfp8_type_node): Add node
        for __mfp8 type.
        (aarch64_mfp8_ptr_type_node): Add node for __mfp8 pointer type.
        (aarch64_init_fp8_types): New function to initialise fp8 types and
        register with language backends.
        * config/aarch64/aarch64.cc (aarch64_invalid_conversion): Add function
        implementing TARGET_INVALID_CONVERSION hook that blocks conversion to
        and from __mfp8 type.
        (aarch64_invalid_unary_op): Add function implementing TARGET_UNARY_OP
        hook that blocks operations on __mfp8 other than &.
        (aarch64_invalid_binary_op): Extend TARGET_BINARY_OP hook to disallow
        operations on __mfp8 type.
        (TARGET_INVALID_CONVERSION): Add define.
        (TARGET_INVALID_UNARY_OP): Likewise.
        * config/aarch64/aarch64.h (aarch64_mfp8_type_node): Add node for __mfp8
        type.
        (aarch64_mfp8_ptr_type_node): Add node for __mfp8 pointer type.
        * config/aarch64/arm_neon.h (mfloat8_t): Add typedef.
        * config/aarch64/arm_sve.h (mfloat8_t): Likewise.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/fp8_scalar_1.c: New tests in C.
        * gcc.target/aarch64/fp8_scalar_typecheck_1.c: Likewise.
        * gcc.target/aarch64/fp8_scalar_typecheck_2.C: New tests in C++.
---

Hi, 
Is this ok for master? I do not have commit rights yet, if ok, can someone 
commit it on my behalf?

Regression tested with aarch64-unknown-linux-gnu.

Thanks,
Claudio Bantaloukas

 gcc/config/aarch64/aarch64-builtins.cc        |  23 ++
 gcc/config/aarch64/aarch64.cc                 |  60 +++
 gcc/config/aarch64/aarch64.h                  |   5 +
 gcc/config/aarch64/arm_neon.h                 |   2 +
 gcc/config/aarch64/arm_sve.h                  |   1 +
 .../gcc.target/aarch64/fp8_scalar_1.c         | 108 ++++++
 .../aarch64/fp8_scalar_typecheck_1.c          | 329 ++++++++++++++++
 .../aarch64/fp8_scalar_typecheck_2.C          | 354 ++++++++++++++++++
 8 files changed, 882 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_2.C

diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc
index 30669f8aa18..22d60df396f 100644
--- a/gcc/config/aarch64/aarch64-builtins.cc
+++ b/gcc/config/aarch64/aarch64-builtins.cc
@@ -961,6 +961,11 @@ static GTY(()) tree aarch64_simd_intOI_type_node = NULL_TREE;
 static GTY(()) tree aarch64_simd_intCI_type_node = NULL_TREE;
 static GTY(()) tree aarch64_simd_intXI_type_node = NULL_TREE;
 
+/* The user-visible __mfp8 type, and a pointer to that type.  Used
+   across the back-end.  */
+tree aarch64_mfp8_type_node = NULL_TREE;
+tree aarch64_mfp8_ptr_type_node = NULL_TREE;
+
 /* The user-visible __fp16 type, and a pointer to that type.  Used
    across the back-end.  */
 tree aarch64_fp16_type_node = NULL_TREE;
@@ -1721,6 +1726,22 @@ aarch64_init_builtin_rsqrt (void)
   }
 }
 
+static void
+aarch64_init_fp8_types (void)
+{
+  aarch64_mfp8_type_node = make_node (INTEGER_TYPE);
+  TYPE_PRECISION (aarch64_mfp8_type_node) = 8;
+  TYPE_MIN_VALUE (aarch64_mfp8_type_node)
+      = TYPE_MIN_VALUE (unsigned_char_type_node);
+  TYPE_MAX_VALUE (aarch64_mfp8_type_node)
+      = TYPE_MAX_VALUE (unsigned_char_type_node);
+  layout_type (aarch64_mfp8_type_node);
+  SET_TYPE_MODE (aarch64_mfp8_type_node, QImode);
+
+  lang_hooks.types.register_builtin_type (aarch64_mfp8_type_node, "__mfp8");
+  aarch64_mfp8_ptr_type_node = build_pointer_type (aarch64_mfp8_type_node);
+}
+
 /* Initialize the backend types that support the user-visible __fp16
    type, also initialize a pointer to that type, to be used when
    forming HFAs.  */
@@ -2128,6 +2149,8 @@ aarch64_general_init_builtins (void)
 {
   aarch64_init_fpsr_fpcr_builtins ();
 
+  aarch64_init_fp8_types ();
+
   aarch64_init_fp16_types ();
 
   aarch64_init_bf16_types ();
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 9810f2c0390..e774b95e430 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -22450,6 +22450,35 @@ aarch64_mangle_type (const_tree type)
   return NULL;
 }
 
+/* Implement TARGET_INVALID_CONVERSION.
+
+Return the diagnostic message when it is invalid to convert from fromtype to
+totype, or NULL if validity should be determined by the front end. */
+
+static const char *
+aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
+{
+  /* Do not allow conversions to/from FP8.  */
+  bool fromtype_is_fp8
+      = ((fromtype) && (TYPE_MODE (fromtype) == QImode)
+	 && (TYPE_MAIN_VARIANT (fromtype) == aarch64_mfp8_type_node));
+  bool totype_is_fp8
+      = ((totype)
+	 && (TYPE_MODE (totype) == QImode
+	     && TYPE_MAIN_VARIANT (totype) == aarch64_mfp8_type_node));
+
+  /* But do allow conversions between volatile and const __mfp8 */
+  if (fromtype_is_fp8 && totype_is_fp8)
+    return NULL;
+
+  if (fromtype_is_fp8)
+    return N_ ("invalid conversion from type %<mfloat8_t%>");
+  if (totype_is_fp8)
+    return N_ ("invalid conversion to type %<mfloat8_t%>");
+  /* Conversion allowed.  */
+  return NULL;
+}
+
 /* Implement TARGET_VERIFY_TYPE_CONTEXT.  */
 
 static bool
@@ -28967,6 +28996,24 @@ aarch64_stack_protect_guard (void)
   return NULL_TREE;
 }
 
+/* Implement TARGET_INVALID_UNARY_OP.
+
+   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 __mfp8 except for &.  */
+  if ((TYPE_MODE (type) == QImode)
+      && (TYPE_MAIN_VARIANT (type) == aarch64_mfp8_type_node)
+      && (op != ADDR_EXPR))
+    return N_ ("operation not permitted on type %<mfloat8_t%>");
+
+  /* Operation allowed.  */
+  return NULL;
+}
+
 /* Return the diagnostic message string if the binary operation OP is
    not permitted on TYPE1 and TYPE2, NULL otherwise.  */
 
@@ -28982,6 +29029,13 @@ aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
 	  != aarch64_sve::builtin_type_p (type2)))
     return N_("cannot combine GNU and SVE vectors in a binary operation");
 
+  /* Reject all 2-operand operations on __mfp8.  */
+  if (((TYPE_MODE (type1) == QImode)
+       && (TYPE_MAIN_VARIANT (type1) == aarch64_mfp8_type_node))
+      || ((TYPE_MODE (type2) == QImode)
+          && (TYPE_MAIN_VARIANT (type2) == aarch64_mfp8_type_node)))
+    return N_ ("operation not permitted on type %<mfloat8_t%>");
+
   /* Operation allowed.  */
   return NULL;
 }
@@ -30699,6 +30753,12 @@ 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
 
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 2dfb999bea5..7ef82ce3587 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -1447,6 +1447,11 @@ extern const char *aarch64_rewrite_mcpu (int argc, const char **argv);
 
 #define ASM_OUTPUT_POOL_EPILOGUE  aarch64_asm_output_pool_epilogue
 
+/* This type is the user-visible __mfp8, and a pointer to that type.  We
+   need it in many places in the backend.  Defined in aarch64-builtins.cc.  */
+extern GTY(()) tree aarch64_mfp8_type_node;
+extern GTY(()) tree aarch64_mfp8_ptr_type_node;
+
 /* This type is the user-visible __fp16, and a pointer to that type.  We
    need it in many places in the backend.  Defined in aarch64-builtins.cc.  */
 extern GTY(()) tree aarch64_fp16_type_node;
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index e376685489d..0092314cf75 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -72,6 +72,8 @@ typedef __Poly16_t poly16_t;
 typedef __Poly64_t poly64_t;
 typedef __Poly128_t poly128_t;
 
+typedef __mfp8 mfloat8_t;
+
 typedef __fp16 float16_t;
 typedef float float32_t;
 typedef double float64_t;
diff --git a/gcc/config/aarch64/arm_sve.h b/gcc/config/aarch64/arm_sve.h
index aa0bd9909f9..61c440fef56 100644
--- a/gcc/config/aarch64/arm_sve.h
+++ b/gcc/config/aarch64/arm_sve.h
@@ -29,6 +29,7 @@
 #include <arm_private_fp8.h>
 #include <arm_bf16.h>
 
+typedef __mfp8 mfloat8_t;
 typedef __fp16 float16_t;
 typedef float float32_t;
 typedef double float64_t;
diff --git a/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c
new file mode 100644
index 00000000000..6925653e33c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c
@@ -0,0 +1,108 @@
+/* Test the fp8 ACLE intrinsics family.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv9.4-a+fp8" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+#include <arm_neon.h>
+
+/*
+**stacktest1:
+**	sub	sp, sp, #16
+**	sxtb	w0, w0
+**	strb	w0, \[sp, 15\]
+**	ldrb	w0, \[sp, 15\]
+**	add	sp, sp, 16
+**	ret
+*/
+mfloat8_t
+stacktest1 (mfloat8_t __a)
+{
+  volatile mfloat8_t b = __a;
+  return b;
+}
+
+/*
+**fp8_mov_ww:
+**	dup	b1, v2.b\[0\]
+**	ret
+*/
+void
+fp8_mov_ww (void)
+{
+  register mfloat8_t x asm ("h2");
+  register mfloat8_t y asm ("h1");
+  asm volatile ("" : "=w"(x));
+  y = x;
+  asm volatile ("" ::"w"(y));
+}
+
+/*
+**fp8_mov_rw:
+**	dup	v1.8b, w1
+**	ret
+*/
+void
+fp8_mov_rw (void)
+{
+  register mfloat8_t x asm ("w1");
+  register mfloat8_t y asm ("h1");
+  asm volatile ("" : "=r"(x));
+  y = x;
+  asm volatile ("" ::"w"(y));
+}
+
+/*
+**fp8_mov_wr:
+**	umov	w1, v1.b\[0\]
+**	ret
+*/
+void
+fp8_mov_wr (void)
+{
+  register mfloat8_t x asm ("h1");
+  register mfloat8_t y asm ("w1");
+  asm volatile ("" : "=w"(x));
+  y = x;
+  asm volatile ("" ::"r"(y));
+}
+
+/*
+**fp8_mov_rr:
+**	mov	w1, w2
+**	ret
+*/
+void
+fp8_mov_rr (void)
+{
+  register mfloat8_t x asm ("w2");
+  register mfloat8_t y asm ("w1");
+  asm volatile ("" : "=r"(x));
+  y = x;
+  asm volatile ("" ::"r"(y));
+}
+
+/*
+**fp8_mov_rm:
+**	strb	w2, \[x0\]
+**	ret
+*/
+void
+fp8_mov_rm (mfloat8_t *ptr)
+{
+  register mfloat8_t x asm ("w2");
+  asm volatile ("" : "=r"(x));
+  *ptr = x;
+}
+
+/*
+**fp8_mov_mr:
+**	ldrb	w2, \[x0\]
+**	ret
+*/
+void
+fp8_mov_mr (mfloat8_t *ptr)
+{
+  register mfloat8_t y asm ("w2");
+  y = *ptr;
+  asm volatile ("" ::"r"(y));
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c
new file mode 100644
index 00000000000..122dc5aa2b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c
@@ -0,0 +1,329 @@
+/* Test that there is no conversion between ints and mfloat8_t.  */
+/* { dg-do assemble } */
+/* { dg-options "-O1 -march=armv9.4-a+fp8" } */
+
+#include <arm_neon.h>
+#include <stdint.h>
+
+mfloat8_t glob_fp8;
+
+int is_an_int;
+uint8_t is_a_uint8;
+int8_t is_an_int8;
+short is_a_short_int;
+float is_a_float;
+double is_a_double;
+
+uint8_t *uint8_ptr;
+
+mfloat8_t
+invalid_from_fp8 (uint16_t __a)
+{
+  mfloat8_t b = __a; // { dg-error "invalid conversion to type 'mfloat8_t'" }
+  return b;
+}
+
+uint16_t
+invalid_to_fp8 (mfloat8_t __a)
+{
+  uint16_t b = __a; // { dg-error "invalid conversion from type 'mfloat8_t'" }
+  return b;
+}
+
+mfloat8_t
+foo1 (void)
+{
+  return (mfloat8_t)0x1234; // { dg-error {invalid conversion to type 'mfloat8_t'} }
+}
+mfloat8_t
+foo2 (void)
+{
+  return (mfloat8_t)(short)0x1234; // { dg-error {invalid conversion to type 'mfloat8_t'} }
+}
+
+mfloat8_t
+footest (mfloat8_t scalar0)
+{
+
+  /* Initialisation  */
+
+  mfloat8_t scalar1_1;
+  mfloat8_t scalar1_2 = glob_fp8;
+  mfloat8_t scalar1_3 = 0; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_4
+      = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_5
+      = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_6
+      = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_8
+      = is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_9
+      = is_a_short_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_10
+      = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_11
+      = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+
+  int initi_1_1
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  float initi_1_2
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  short initi_1_4
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  double initi_1_5
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  uint8_t initi_1_6
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  int8_t initi_1_7
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  mfloat8_t scalar2_1 = {};
+  mfloat8_t scalar2_2 = { glob_fp8 };
+  mfloat8_t scalar2_3
+      = { 0 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar2_4
+      = { 0.1 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar2_5
+      = { is_a_float }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar2_6
+      = { is_an_int }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar2_8 = {
+    is_a_double
+  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar2_9 = {
+    is_a_short_int
+  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar2_10
+      = { is_a_uint8 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar2_11
+      = { is_an_int8 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+
+  int initi_2_1
+      = { glob_fp8 }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  float initi_2_2
+      = { glob_fp8 }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  short initi_2_4
+      = { glob_fp8 }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  double initi_2_5
+      = { glob_fp8 }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  uint8_t initi_2_6
+      = { glob_fp8 }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  int8_t initi_2_7
+      = { glob_fp8 }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  /* Assignments.  */
+
+  glob_fp8 = glob_fp8;
+  glob_fp8 = 0;	  /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8 = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_a_float;	/* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8 = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_a_short_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+
+  is_an_int
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_float
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_double
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_short_int
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_uint8
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_an_int8
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  /* Casting.  */
+
+  (void)glob_fp8;
+  (mfloat8_t) glob_fp8;
+
+  (int)glob_fp8;     /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (float)glob_fp8;   /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (double)glob_fp8;  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (short)glob_fp8;   /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (uint8_t)glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (int8_t)glob_fp8;  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  (mfloat8_t) is_an_int;	/* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t) is_a_float;	/* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t) is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t)
+      is_a_short_int;  /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t) is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t) is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+
+  /* Compound literals.  */
+
+  (mfloat8_t){};
+  (mfloat8_t){ glob_fp8 };
+  (mfloat8_t){ 0 };   /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t){ 0.1 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t){
+    is_a_float
+  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t){
+    is_an_int
+  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t){
+    is_a_double
+  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t){
+    is_a_short_int
+  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t){
+    is_a_uint8
+  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t){
+    is_an_int8
+  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+
+  (int){ glob_fp8 }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (float){
+    glob_fp8
+  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (double){
+    glob_fp8
+  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (short){
+    glob_fp8
+  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (uint8_t){
+    glob_fp8
+  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (int8_t){
+    glob_fp8
+  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  /* Arrays and Structs.  */
+
+  typedef mfloat8_t array_type[2];
+  extern mfloat8_t extern_array[];
+
+  mfloat8_t array[2];
+  mfloat8_t zero_length_array[0];
+  mfloat8_t empty_init_array[] = {};
+  typedef mfloat8_t some_other_type[is_an_int];
+
+  struct struct1
+  {
+    mfloat8_t a;
+  };
+
+  union union1
+  {
+    mfloat8_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  mfloat8_t *fp8_ptr = &scalar0;
+  scalar0 = *fp8_ptr;
+
+  /* Pointer assignment.  */
+
+  mfloat8_t *fp8_ptr2 = fp8_ptr;
+  mfloat8_t *fp8_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++fp8_ptr;
+  --fp8_ptr;
+  fp8_ptr++;
+  fp8_ptr--;
+  fp8_ptr += 1;
+  fp8_ptr -= 1;
+  fp8_ptr - fp8_ptr2;
+  fp8_ptr = &fp8_ptr3[0];
+  fp8_ptr = &fp8_ptr3[1];
+
+  /* Simple comparison.  */
+  scalar0 > glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  glob_fp8
+      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 > is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_float
+      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 > 0;	  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 == scalar0;	  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 > 0.1;  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0.1 == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0
+      > is_an_int; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_an_int
+      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  /* Pointer comparison.  */
+
+  fp8_ptr == &scalar0;
+  fp8_ptr != &scalar0;
+  fp8_ptr < &scalar0;
+  fp8_ptr <= &scalar0;
+  fp8_ptr > &scalar0;
+  fp8_ptr >= &scalar0;
+  fp8_ptr == fp8_ptr2;
+  fp8_ptr != fp8_ptr2;
+  fp8_ptr < fp8_ptr2;
+  fp8_ptr <= fp8_ptr2;
+  fp8_ptr > fp8_ptr2;
+  fp8_ptr >= fp8_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? scalar0 : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? scalar0
+    : is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? is_a_float
+    : scalar0;	     /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? scalar0 : 0;   /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? 0 : scalar0;   /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? fp8_ptr : fp8_ptr2;
+  0 ? fp8_ptr : uint8_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+  0 ? uint8_ptr : fp8_ptr; /* { dg-error {pointer type mismatch in conditional expression} } */
+
+  scalar0 ? scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+	  : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 ? is_a_float /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+	  : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 ? is_a_float : is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  /* Unary operators.  */
+
+  +scalar0;	  /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  -scalar0;	  /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  ~scalar0;	  /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  !scalar0;	  /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  *scalar0;	  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  __real scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  __imag scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  ++scalar0;	  /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  --scalar0;	  /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  scalar0++;	  /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  scalar0--;	  /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+
+  /* Binary arithmetic operations.  */
+
+  scalar0 = glob_fp8 + scalar1_2; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 = glob_fp8 + *fp8_ptr; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 = glob_fp8
+	    + 0.1; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0
+      = glob_fp8 + 0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0
+      = glob_fp8
+	+ is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  return scalar0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_2.C b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_2.C
new file mode 100644
index 00000000000..f0a3c756c84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_2.C
@@ -0,0 +1,354 @@
+/* Test that mfloat8_t is only usable with intrinsics, thus not convertible.  */
+/* { dg-do assemble } */
+/* { dg-options "-O1 -march=armv9.4-a+fp8 -Wno-narrowing" } */
+
+#include <arm_neon.h>
+#include <stdint.h>
+
+mfloat8_t glob_fp8;
+
+int is_an_int;
+uint8_t is_a_uint8;
+int8_t is_an_int8;
+short is_a_short_int;
+float is_a_float;
+double is_a_double;
+
+uint8_t *uint8_ptr;
+
+mfloat8_t
+invalid_from_fp8 (uint16_t __a)
+{
+  mfloat8_t b = __a; /* { dg-error "invalid conversion to type 'mfloat8_t'" } */
+  return b;
+}
+
+uint16_t
+invalid_to_fp8 (mfloat8_t __a)
+{
+  uint16_t b = __a; /*{ dg-error "invalid conversion from type 'mfloat8_t'" } */
+  return b;
+}
+
+mfloat8_t
+foo1 (void)
+{
+  return (mfloat8_t)0x1234; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+}
+
+mfloat8_t
+foo2 (void)
+{
+  return (mfloat8_t)(short)0x1234; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+}
+
+mfloat8_t
+footest (mfloat8_t scalar0)
+{
+
+  /* Initialisation  */
+
+  mfloat8_t scalar1_1;
+  mfloat8_t scalar1_2 = glob_fp8;
+  mfloat8_t scalar1_3
+      = 0; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_4
+      = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_5
+      = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_6
+      = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_8
+      = is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_10
+      = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar1_11
+      = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+
+  int initi_1_1
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  float initi_1_2
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  short initi_1_4
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  double initi_1_5
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  uint8_t initi_1_6
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  int8_t initi_1_7
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  mfloat8_t scalar2_1 = {};
+  mfloat8_t scalar2_2 = { glob_fp8 };
+  mfloat8_t scalar2_3
+      = { 0 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar2_4
+      = { 0.1 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  mfloat8_t scalar2_5 = {
+    is_a_float /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  mfloat8_t scalar2_6 = {
+    is_an_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  mfloat8_t scalar2_8 = {
+    is_a_double /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  mfloat8_t scalar2_9 = {
+    is_a_short_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  mfloat8_t scalar2_10 = {
+    is_a_uint8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  mfloat8_t scalar2_11 = {
+    is_an_int8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+
+  int initi_2_1 = {
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  float initi_2_2 = {
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  short initi_2_4 = {
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  double initi_2_5 = {
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  uint8_t initi_2_6 = {
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  int8_t initi_2_7 = {
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+
+  /* Assignments.  */
+
+  glob_fp8 = glob_fp8;
+  glob_fp8 = 0;	  /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8 = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8 = is_a_short_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  glob_fp8
+      = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+
+  is_an_int
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_float
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_double
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_short_int
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_uint8
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_an_int8
+      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  /* Casting.  */
+
+  (void)glob_fp8;
+  (mfloat8_t) glob_fp8;
+
+  (int)glob_fp8;   /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (float)glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (double)
+      glob_fp8;	   /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (short)glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (uint8_t)
+      glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  (int8_t)
+      glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  (mfloat8_t)
+      is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t)
+      is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t)
+      is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t) is_a_short_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t)
+      is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t)
+      is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+
+  /* Compound literals.  */
+
+  (mfloat8_t){};
+  (mfloat8_t){ glob_fp8 };
+  (mfloat8_t){ 0 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  (mfloat8_t){
+    0.1 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  }; 
+  (mfloat8_t){
+    is_a_float /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  (mfloat8_t){
+    is_an_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  (mfloat8_t){
+    is_a_double /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  (mfloat8_t){
+    is_a_short_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  (mfloat8_t){
+    is_a_uint8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+  (mfloat8_t){
+    is_an_int8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
+  };
+
+  (int){
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  (float){
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  (double){
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  (short){
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  (uint8_t){
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+  (int8_t){
+    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  };
+
+  /* Arrays and Structs.  */
+
+  typedef mfloat8_t array_type[2];
+  extern mfloat8_t extern_array[];
+
+  mfloat8_t array[2];
+  mfloat8_t zero_length_array[0];
+  mfloat8_t empty_init_array[] = {};
+  typedef mfloat8_t some_other_type[is_an_int];
+
+  struct struct1
+  {
+    mfloat8_t a;
+  };
+
+  union union1
+  {
+    mfloat8_t a;
+  };
+
+  /* Addressing and dereferencing.  */
+
+  mfloat8_t *fp8_ptr = &scalar0;
+  scalar0 = *fp8_ptr;
+
+  /* Pointer assignment.  */
+
+  mfloat8_t *fp8_ptr2 = fp8_ptr;
+  mfloat8_t *fp8_ptr3 = array;
+
+  /* Pointer arithmetic.  */
+
+  ++fp8_ptr;
+  --fp8_ptr;
+  fp8_ptr++;
+  fp8_ptr--;
+  fp8_ptr += 1;
+  fp8_ptr -= 1;
+  fp8_ptr - fp8_ptr2;
+  fp8_ptr = &fp8_ptr3[0];
+  fp8_ptr = &fp8_ptr3[1];
+
+  /* Simple comparison.  */
+  scalar0
+      > glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  glob_fp8
+      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 > is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_a_float
+      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 > 0;	  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 == scalar0;	  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 > 0.1;  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0.1 == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0
+      > is_an_int; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  is_an_int
+      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  /* Pointer comparison.  */
+
+  fp8_ptr == &scalar0;
+  fp8_ptr != &scalar0;
+  fp8_ptr < &scalar0;
+  fp8_ptr <= &scalar0;
+  fp8_ptr > &scalar0;
+  fp8_ptr >= &scalar0;
+  fp8_ptr == fp8_ptr2;
+  fp8_ptr != fp8_ptr2;
+  fp8_ptr < fp8_ptr2;
+  fp8_ptr <= fp8_ptr2;
+  fp8_ptr > fp8_ptr2;
+  fp8_ptr >= fp8_ptr2;
+
+  /* Conditional expressions.  */
+
+  0 ? scalar0 : scalar0;
+  0 ? scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+    : is_a_float;
+  0 ? is_a_float
+    : scalar0;	   /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? scalar0 : 0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? 0 : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? 0.1
+    : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  0 ? scalar0  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+    : 0.1;
+  0 ? fp8_ptr : fp8_ptr2;
+  0 ? fp8_ptr : uint8_ptr; /* { dg-error {conditional expression between distinct pointer types} } */
+  0 ? uint8_ptr : fp8_ptr; /* { dg-error {conditional expression between distinct pointer types} } */
+
+  scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+      ? scalar0
+      : scalar0;
+  scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+      ? is_a_float
+      : scalar0;
+  scalar0 ? scalar0 : is_a_float;    /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 ? is_a_float : is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  /* Unary operators.  */
+
+  +scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  -scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  ~scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  !scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  *scalar0; /* { dg-error {invalid type argument of unary} } */
+  __real scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  __imag scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  ++scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  --scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  scalar0++; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+  scalar0--; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+
+  /* Binary arithmetic operations.  */
+
+  scalar0 = glob_fp8 + scalar1_2; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 = glob_fp8 + *fp8_ptr;  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 = glob_fp8
+	    + 0.1; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 = glob_fp8
+	    + 0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+  scalar0 = glob_fp8 + is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+  return scalar0;
+}

Reply via email to