[v3] aarch64: Add fp8 scalar types
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
Commit Message
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 unsigned 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_mangle_type): Add ABI mangling for
new type.
(aarch64_invalid_conversion): Add function implementing
TARGET_INVALID_CONVERSION hook that blocks conversion to and from the
__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_private_fp8.h (mfloat8_t): Add typedef.
gcc/testsuite/ChangeLog:
* g++.target/aarch64/fp8_mangling.C: New tests exercising mangling.
* g++.target/aarch64/fp8_scalar_typecheck_2.C: New tests in C++.
* gcc.target/aarch64/fp8_scalar_1.c: New tests in C.
* gcc.target/aarch64/fp8_scalar_typecheck_1.c: Likewise.
---
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.
Compared to V1 of the patch, in version 2:
- mangling for the __mfp8 type was added along with tests
- unneeded comments were removed
- simplified type checks in hooks
- simplified initialization of aarch64_mfp8_type_node
- separated mfloat8_t define from other fp types in arm_sve.h
- C++ tests were moved to g++.target/aarch64
- added more tests around binary operations, function declaration,
type traits
- added tests exercising loads and stores from floating point registers
Compared to V2 of the patch, in version 3:
- typedefs for mfloat8_t are defined in arm_private_fp8.h rather than arm_neon.h and arm_sve.h
Thanks,
Claudio Bantaloukas
gcc/config/aarch64/aarch64-builtins.cc | 20 +
gcc/config/aarch64/aarch64.cc | 54 ++-
gcc/config/aarch64/aarch64.h | 5 +
gcc/config/aarch64/arm_private_fp8.h | 2 +
.../g++.target/aarch64/fp8_mangling.C | 44 ++
.../aarch64/fp8_scalar_typecheck_2.C | 381 ++++++++++++++++++
.../gcc.target/aarch64/fp8_scalar_1.c | 134 ++++++
.../aarch64/fp8_scalar_typecheck_1.c | 356 ++++++++++++++++
8 files changed, 994 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/g++.target/aarch64/fp8_mangling.C
create mode 100644 gcc/testsuite/g++.target/aarch64/fp8_scalar_typecheck_2.C
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
Comments
Claudio Bantaloukas <claudio.bantaloukas@arm.com> writes:
> 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 unsigned 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_mangle_type): Add ABI mangling for
> new type.
> (aarch64_invalid_conversion): Add function implementing
> TARGET_INVALID_CONVERSION hook that blocks conversion to and from the
> __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_private_fp8.h (mfloat8_t): Add typedef.
>
> gcc/testsuite/ChangeLog:
>
> * g++.target/aarch64/fp8_mangling.C: New tests exercising mangling.
> * g++.target/aarch64/fp8_scalar_typecheck_2.C: New tests in C++.
> * gcc.target/aarch64/fp8_scalar_1.c: New tests in C.
> * gcc.target/aarch64/fp8_scalar_typecheck_1.c: Likewise.
> ---
> Hi,
> Is this ok for master? I do not have commit rights yet, if ok, can someone commit it on my behalf?
LGTM, thanks. Give it a day or so to see if Kyrill has any comments,
but otherwise ok for trunk. (Please ask someone else to push it though,
since I won't be around next week.)
Richard
I just pushed it to the trunk.
Thanks,
Saurabh
On 9/20/2024 3:09 PM, Claudio Bantaloukas wrote:
>
> 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 unsigned 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_mangle_type): Add ABI mangling for
> new type.
> (aarch64_invalid_conversion): Add function implementing
> TARGET_INVALID_CONVERSION hook that blocks conversion to and from the
> __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_private_fp8.h (mfloat8_t): Add typedef.
>
> gcc/testsuite/ChangeLog:
>
> * g++.target/aarch64/fp8_mangling.C: New tests exercising mangling.
> * g++.target/aarch64/fp8_scalar_typecheck_2.C: New tests in C++.
> * gcc.target/aarch64/fp8_scalar_1.c: New tests in C.
> * gcc.target/aarch64/fp8_scalar_typecheck_1.c: Likewise.
> ---
> 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.
>
> Compared to V1 of the patch, in version 2:
> - mangling for the __mfp8 type was added along with tests
> - unneeded comments were removed
> - simplified type checks in hooks
> - simplified initialization of aarch64_mfp8_type_node
> - separated mfloat8_t define from other fp types in arm_sve.h
> - C++ tests were moved to g++.target/aarch64
> - added more tests around binary operations, function declaration,
> type traits
> - added tests exercising loads and stores from floating point registers
>
> Compared to V2 of the patch, in version 3:
> - typedefs for mfloat8_t are defined in arm_private_fp8.h rather than arm_neon.h and arm_sve.h
>
> Thanks,
> Claudio Bantaloukas
>
> gcc/config/aarch64/aarch64-builtins.cc | 20 +
> gcc/config/aarch64/aarch64.cc | 54 ++-
> gcc/config/aarch64/aarch64.h | 5 +
> gcc/config/aarch64/arm_private_fp8.h | 2 +
> .../g++.target/aarch64/fp8_mangling.C | 44 ++
> .../aarch64/fp8_scalar_typecheck_2.C | 381 ++++++++++++++++++
> .../gcc.target/aarch64/fp8_scalar_1.c | 134 ++++++
> .../aarch64/fp8_scalar_typecheck_1.c | 356 ++++++++++++++++
> 8 files changed, 994 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/g++.target/aarch64/fp8_mangling.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/fp8_scalar_typecheck_2.C
> 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
>
@@ -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,19 @@ aarch64_init_builtin_rsqrt (void)
}
}
+/* Initialize the backend type that supports the user-visible __mfp8
+ type and its relative pointer type. */
+
+static void
+aarch64_init_fp8_types (void)
+{
+ aarch64_mfp8_type_node = make_unsigned_type (8);
+ 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. */
@@ -2125,6 +2143,8 @@ aarch64_general_init_builtins (void)
{
aarch64_init_fpsr_fpcr_builtins ();
+ aarch64_init_fp8_types ();
+
aarch64_init_fp16_types ();
aarch64_init_bf16_types ();
@@ -22467,6 +22467,10 @@ aarch64_mangle_type (const_tree type)
return "Dh";
}
+ /* Modal 8 bit floating point types. */
+ if (TYPE_MAIN_VARIANT (type) == aarch64_mfp8_type_node)
+ return "u6__mfp8";
+
/* Mangle AArch64-specific internal types. TYPE_NAME is non-NULL_TREE for
builtin types. */
if (TYPE_NAME (type) != NULL)
@@ -22481,6 +22485,29 @@ aarch64_mangle_type (const_tree type)
return NULL;
}
+/* Implement TARGET_INVALID_CONVERSION. */
+
+static const char *
+aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
+{
+ /* Do not allow conversions to/from FP8. But do allow conversions between
+ volatile and const variants of __mfp8. */
+ bool fromtype_is_fp8
+ = (TYPE_MAIN_VARIANT (fromtype) == aarch64_mfp8_type_node);
+ bool totype_is_fp8 = (TYPE_MAIN_VARIANT (totype) == aarch64_mfp8_type_node);
+
+ 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
@@ -29031,8 +29058,20 @@ aarch64_stack_protect_guard (void)
return NULL_TREE;
}
-/* Return the diagnostic message string if the binary operation OP is
- not permitted on TYPE1 and TYPE2, NULL otherwise. */
+/* Implement TARGET_INVALID_UNARY_OP. */
+
+static const char *
+aarch64_invalid_unary_op (int op, const_tree type)
+{
+ /* Reject all single-operand operations on __mfp8 except for &. */
+ if (TYPE_MAIN_VARIANT (type) == aarch64_mfp8_type_node && op != ADDR_EXPR)
+ return N_ ("operation not permitted on type %<mfloat8_t%>");
+
+ /* Operation allowed. */
+ return NULL;
+}
+
+/* Implement TARGET_INVALID_BINARY_OP. */
static const char *
aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
@@ -29046,6 +29085,11 @@ 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_MAIN_VARIANT (type1) == aarch64_mfp8_type_node
+ || TYPE_MAIN_VARIANT (type2) == aarch64_mfp8_type_node)
+ return N_ ("operation not permitted on type %<mfloat8_t%>");
+
/* Operation allowed. */
return NULL;
}
@@ -30763,6 +30807,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
@@ -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;
@@ -40,6 +40,8 @@ extern "C"
{
#endif
+ typedef __mfp8 mfloat8_t;
+
typedef uint64_t fpm_t;
enum __ARM_FPM_FORMAT
new file mode 100644
@@ -0,0 +1,44 @@
+/* Test that mfloat8_t mangles differently from uint8_t */
+/* { dg-options "-O1 -march=armv9.4-a+fp8" } */
+
+int
+foo (__mfp8)
+{
+ return 1;
+}
+
+int
+foo (unsigned char)
+{
+ return 2;
+}
+
+int
+bar (__mfp8 x)
+{
+ return foo (x);
+}
+/* { dg-final { scan-assembler-times "\n_Z3fooh:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foou6__mfp8:\n" 1 } } */
+
+constexpr __mfp8 cfp8{};
+
+constexpr int
+fooc (unsigned char)
+{
+ return 3;
+}
+
+constexpr int
+fooc (__mfp8)
+{
+ return 4;
+}
+
+constexpr int
+barc (__mfp8 x)
+{
+ return fooc (x);
+}
+
+static_assert (barc (cfp8) == 4, "constexpr selects incorrect overload");
new file mode 100644
@@ -0,0 +1,381 @@
+/* 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>
+#include <type_traits>
+
+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'} } */
+
+ glob_fp8 + glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+ glob_fp8 - glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+ glob_fp8 * glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+ glob_fp8 / glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+ glob_fp8 && glob_fp8; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+ glob_fp8 || glob_fp8; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
+
+ return scalar0;
+}
+
+/* Check that function decls for mfloat8_t and unsigned char differ */
+
+mfloat8_t extern_fn1(void);
+unsigned char extern_fn1(void); /* { dg-error {ambiguating new declaration of 'unsigned char extern_fn1\(\)'} } */
+
+mfloat8_t extern_fn2(void);
+uint8_t extern_fn2(void); /* { dg-error {ambiguating new declaration of 'uint8_t extern_fn2\(\)} } */
+
+unsigned char extern_fn3(void);
+mfloat8_t extern_fn3(void); /* { dg-error {ambiguating new declaration of 'mfloat8_t extern_fn3\(\)} } */
+
+uint8_t extern_fn4(void);
+mfloat8_t extern_fn4(void); /* { dg-error {ambiguating new declaration of 'mfloat8_t extern_fn4\(\)} } */
+
+/* Check that the type conforms to the contract */
+static_assert(!std::is_integral<__mfp8>(), "not integral");
+static_assert(!std::is_signed<__mfp8>(), "not signed");
+static_assert(!std::is_unsigned<__mfp8>(), "not unsigned");
new file mode 100644
@@ -0,0 +1,134 @@
+/* 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
+** and w0, w0, 255
+** 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));
+}
+
+/*
+**fp8_str_r:
+** str b2, \[x0\]
+** ret
+*/
+void
+fp8_str_r (mfloat8_t *ptr)
+{
+ register mfloat8_t x asm ("v2");
+ asm volatile ("" : "=w"(x));
+ *ptr = x;
+}
+
+/*
+**fp8_ldr_r:
+** ldr b2, \[x0\]
+** ret
+*/
+void
+fp8_ldr_r (mfloat8_t *ptr)
+{
+ register mfloat8_t y asm ("v2");
+ y = *ptr;
+ asm volatile ("" ::"w"(y));
+}
new file mode 100644
@@ -0,0 +1,356 @@
+/* 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'} } */
+
+ glob_fp8 + glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+ glob_fp8 - glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+ glob_fp8 * glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+ glob_fp8 / glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+ glob_fp8 && glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+ glob_fp8 || glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
+
+ return scalar0;
+}
+
+/* Check that function decls for mfloat8_t and unsigned char differ */
+
+mfloat8_t extern_fn1(void);
+unsigned char extern_fn1(void); /* { dg-error {conflicting types for 'extern_fn1'; have 'unsigned char\(void\)'} } */
+
+mfloat8_t extern_fn2(void);
+uint8_t extern_fn2(void); /* { dg-error {conflicting types for 'extern_fn2'; have 'uint8_t\(void\)'} } */
+
+unsigned char extern_fn3(void);
+mfloat8_t extern_fn3(void); /* { dg-error {conflicting types for 'extern_fn3'; have 'mfloat8_t\(void\)'} } */
+
+uint8_t extern_fn4(void);
+mfloat8_t extern_fn4(void); /* { dg-error {conflicting types for 'extern_fn4'; have 'mfloat8_t\(void\)'} } */
+
+void extern_fn5(mfloat8_t);
+void extern_fn5(unsigned char); /* { dg-error {conflicting types for 'extern_fn5'; have 'void\(unsigned char\)'} } */
+
+void extern_fn6(mfloat8_t);
+void extern_fn6(uint8_t); /* { dg-error {conflicting types for 'extern_fn6'; have 'void\(uint8_t\)'} } */