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_neon.h (mfloat8_t): Add typedef. * config/aarch64/arm_sve.h (mfloat8_t): Likewise. 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 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_neon.h | 2 + gcc/config/aarch64/arm_sve.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 ++++++++++++++++ 9 files changed, 996 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
diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index eb878b933fe..7d17df05a0f 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,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 (); diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 92763d403c7..0ac00027502 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -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 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..dbc61650df2 100644 --- a/gcc/config/aarch64/arm_sve.h +++ b/gcc/config/aarch64/arm_sve.h @@ -29,6 +29,8 @@ #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/g++.target/aarch64/fp8_mangling.C b/gcc/testsuite/g++.target/aarch64/fp8_mangling.C new file mode 100644 index 00000000000..1dfcaa71f15 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/fp8_mangling.C @@ -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"); diff --git a/gcc/testsuite/g++.target/aarch64/fp8_scalar_typecheck_2.C b/gcc/testsuite/g++.target/aarch64/fp8_scalar_typecheck_2.C new file mode 100644 index 00000000000..61557c95663 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/fp8_scalar_typecheck_2.C @@ -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"); 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..1bc2ac26b2a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c @@ -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)); +} 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..9169f40c4b7 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c @@ -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\)'} } */