Skip to content

Commit

Permalink
[CLANG][AArch64] Add the modal 8 bit floating-point scalar type
Browse files Browse the repository at this point in the history
ARM ACLE PR#323[1] adds new modal types for 8-bit floating point intrinsic.

From the PR#323:
```
ACLE defines the `__mfp8` type, which can be used for the E5M2 and E4M3
8-bit floating-point formats. It is a storage and interchange only type
with no arithmetic operations other than intrinsic calls.
````

The type should be an opaque type and its format in undefined in Clang.
Only defined in the backend by a status/format register, for AArch64 the FPMR.

This patch is an attempt to the add the MFloat8_t scalar type.
It has a parser and codegen for the new scalar type.

The patch it is lowering to and 8bit unsigned as it has no format.
But maybe we should add another opaque type.

[1]  ARM-software/acle#323
  • Loading branch information
CarolineConcatto committed Oct 24, 2024
1 parent 629d980 commit eb12648
Show file tree
Hide file tree
Showing 14 changed files with 222 additions and 3 deletions.
13 changes: 13 additions & 0 deletions clang/include/clang/Basic/AArch64SVEACLETypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@
AARCH64_VECTOR_TYPE(Name, MangledName, Id, SingletonId)
#endif

#ifndef AARCH64_SCALAR_TYPE
#define AARCH64_SCALAR_TYPE(Name, MangledName, Id, SingletonId) \
SVE_TYPE(Name, Id, SingletonId)
#endif

#ifndef AARCH64_SCALAR_TYPE_MFLOAT
#define AARCH64_SCALAR_TYPE_MFLOAT(Name, MangledName, Id, SingletonId, NumEls, ElBits, NF) \
AARCH64_SCALAR_TYPE(Name, MangledName, Id, SingletonId)
#endif

//===- Vector point types -----------------------------------------------===//

Expand Down Expand Up @@ -204,6 +213,8 @@ SVE_OPAQUE_TYPE("__SVCount_t", "__SVCount_t", SveCount, SveCountTy)
AARCH64_VECTOR_TYPE_MFLOAT("__MFloat8x8_t", "__MFloat8x8_t", MFloat8x8, MFloat8x8Ty, 8, 8, 1)
AARCH64_VECTOR_TYPE_MFLOAT("__MFloat8x16_t", "__MFloat8x16_t", MFloat8x16, MFloat8x16Ty, 16, 8, 1)

AARCH64_SCALAR_TYPE_MFLOAT("__MFloat8_t", "__MFloat8_t", MFloat8, MFloat8Ty, 1, 8, 1)

#undef SVE_VECTOR_TYPE
#undef SVE_VECTOR_TYPE_BFLOAT
#undef SVE_VECTOR_TYPE_FLOAT
Expand All @@ -213,4 +224,6 @@ AARCH64_VECTOR_TYPE_MFLOAT("__MFloat8x16_t", "__MFloat8x16_t", MFloat8x16, MFloa
#undef SVE_OPAQUE_TYPE
#undef AARCH64_VECTOR_TYPE_MFLOAT
#undef AARCH64_VECTOR_TYPE
#undef AARCH64_SCALAR_TYPE_MFLOAT
#undef AARCH64_SCALAR_TYPE
#undef SVE_TYPE
2 changes: 1 addition & 1 deletion clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,7 @@ enum PredefinedTypeIDs {
///
/// Type IDs for non-predefined types will start at
/// NUM_PREDEF_TYPE_IDs.
const unsigned NUM_PREDEF_TYPE_IDS = 511;
const unsigned NUM_PREDEF_TYPE_IDS = 512;

// Ensure we do not overrun the predefined types we reserved
// in the enum PredefinedTypeIDs above.
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2245,6 +2245,11 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = NumEls * ElBits * NF; \
Align = NumEls * ElBits; \
break;
#define AARCH64_SCALAR_TYPE(Name, MangledName, Id, SingletonId) \
case BuiltinType::Id: \
Width = 8; \
Align = 8; \
break;
#include "clang/Basic/AArch64SVEACLETypes.def"
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id: \
Expand Down Expand Up @@ -4372,6 +4377,11 @@ ASTContext::getBuiltinVectorTypeInfo(const BuiltinType *Ty) const {
case BuiltinType::Id: \
return {getIntTypeForBitwidth(ElBits, false), \
llvm::ElementCount::getFixed(NumEls), NF};
#define AARCH64_SCALAR_TYPE_MFLOAT(Name, MangledName, Id, SingletonId, NumEls, \
ElBits, NF) \
case BuiltinType::Id: \
return {getIntTypeForBitwidth(ElBits, false), \
llvm::ElementCount::getFixed(NumEls), NF};
#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingletonId)
#include "clang/Basic/AArch64SVEACLETypes.def"

Expand Down Expand Up @@ -4439,6 +4449,7 @@ QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts,
return SingletonId;
#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingletonId)
#define AARCH64_VECTOR_TYPE(Name, MangledName, Id, SingletonId)
#define AARCH64_SCALAR_TYPE(Name, MangledName, Id, SingletonId)
#include "clang/Basic/AArch64SVEACLETypes.def"
} else if (Target->hasRISCVVTypes()) {
uint64_t EltTySize = getTypeSize(EltTy);
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3435,6 +3435,11 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
type_name = MangledName; \
Out << (type_name == Name ? "u" : "") << type_name.size() << type_name; \
break;
#define AARCH64_SCALAR_TYPE(Name, MangledName, Id, SingletonId) \
case BuiltinType::Id: \
type_name = MangledName; \
Out << (type_name == Name ? "u" : "") << type_name.size() << type_name; \
break;
#include "clang/Basic/AArch64SVEACLETypes.def"
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id: \
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2496,6 +2496,9 @@ bool Type::isSVESizelessBuiltinType() const {
#define AARCH64_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \
case BuiltinType::Id: \
return false;
#define AARCH64_SCALAR_TYPE(Name, MangledName, Id, SingletonId) \
case BuiltinType::Id: \
return false;
#include "clang/Basic/AArch64SVEACLETypes.def"
default:
return false;
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/AArch64SVEACLETypes.def"
{
if (BT->getKind() == BuiltinType::MFloat8) {
Encoding = llvm::dwarf::DW_ATE_unsigned_char;
BTName = BT->getName(CGM.getLangOpts());
// Bit size and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(BT);
return DBuilder.createBasicType(BTName, Size, Encoding);
}
ASTContext::BuiltinVectorTypeInfo Info =
// For svcount_t, only the lower 2 bytes are relevant.
BT->getKind() == BuiltinType::SveCount
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case BuiltinType::Id:
#define AARCH64_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \
case BuiltinType::Id:
#define AARCH64_SCALAR_TYPE(Name, MangledName, Id, SingletonId) \
case BuiltinType::Id:
#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingletonId)
#include "clang/Basic/AArch64SVEACLETypes.def"
{
Expand Down
91 changes: 91 additions & 0 deletions clang/test/AST/arm-mfp8.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// RUN: %clang_cc1 -std=c++11 -triple aarch64-arm-none-eabi -target-feature -fp8 -ast-dump %s | \
// RUN: FileCheck %s --strict-whitespace

// REQUIRES: aarch64-registered-target || arm-registered-target

/* Various contexts where type __mfp8 can appear. */

#include<arm_neon.h>
/* Namespace */
namespace {
__mfp8 f2n;
__mfp8 arr1n[10];
}

//CHECK: |-NamespaceDecl {{.*}}
//CHECK-NEXT: | |-VarDecl {{.*}} f2n '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | `-VarDecl {{.*}} arr1n '__mfp8[10]'


const __mfp8 func1n(const __mfp8 mfp8) {
// this should fail
__mfp8 f1n;
f1n = mfp8;
return f1n;
}
//CHECK: |-FunctionDecl {{.*}} func1n 'const __mfp8 (const __mfp8)'
//CHECK: | `-VarDecl {{.*}} f1n '__mfp8':'__MFloat8_t'
//CHECK-NEXT: |-BinaryOperator {{.*}} '__mfp8':'__MFloat8_t' lvalue '='
//CHECK-NEXT: | |-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue Var {{.*}} 'f1n' '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
//CHECK-NEXT: | `-DeclRefExpr {{.*}} 'const __mfp8':'const __MFloat8_t' lvalue ParmVar {{.*}} 'mfp8' 'const __mfp8':'const __MFloat8_t'
//CHECK-NEXT: `-ReturnStmt {{.*}}
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
//CHECK-NEXT: `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue Var {{.*}} 'f1n' '__mfp8':'__MFloat8_t'


/* Class */

class C1 {
__mfp8 f1c;
static const __mfp8 f2c;
volatile __MFloat8_t f3c;
public:
C1(__mfp8 arg) : f1c(arg), f3c(arg) { }
__mfp8 func1c(__mfp8 arg ) {
return arg;
}
static __mfp8 func2c(__mfp8 arg) {
return arg;
}
};

//CHECK: | |-CXXRecordDecl {{.*}} referenced class C1
//CHECK-NEXT: | |-FieldDecl {{.*}} f1c '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | |-VarDecl {{.*}} f2c 'const __mfp8':'const __MFloat8_t' static
//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile __MFloat8_t'
//CHECK-NEXT: | |-AccessSpecDecl {{.*}}
//CHECK-NEXT: | |-CXXConstructorDecl {{.*}} C1 'void (__mfp8)' implicit-inline
//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f1c' '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f3c' 'volatile __MFloat8_t'
//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | | `-CompoundStmt {{.*}}
//CHECK-NEXT: | |-CXXMethodDecl {{.*}} func1c '__mfp8 (__mfp8)' implicit-inline
//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | | `-CompoundStmt {{.*}}
//CHECK-NEXT: | | `-ReturnStmt {{.*}}
//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}}8 'arg' '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | `-CXXMethodDecl {{.*}} func2c '__mfp8 (__mfp8)' static implicit-inline
//CHECK-NEXT: | |-ParmVarDecl {{.*}} arg '__mfp8':'__MFloat8_t'
//CHECK-NEXT: | `-CompoundStmt {{.*}}
//CHECK-NEXT: | `-ReturnStmt {{.*}}
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t'

template <class C> struct S1 {
C mem1;
};

template <> struct S1<__mfp8> {
__mfp8 mem2;
};

//CHECK: |-TemplateArgument type '__MFloat8_t'
//CHECK-NEXT: | `-BuiltinType {{.*}} '__MFloat8_t'
//CHECK-NEXT: |-CXXRecordDecl {{.*}} implicit struct S1
//CHECK-NEXT: `-FieldDecl {{.*}} mem2 '__mfp8':'__MFloat8_t'
9 changes: 9 additions & 0 deletions clang/test/CodeGen/aarch64-debug-types.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon -target-feature +fp8 \
// RUN: -emit-llvm -o - %s -debug-info-kind=limited 2>&1 | FileCheck %s
#include<arm_neon.h>

void test_locals(void) {
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "__MFloat8_t", {{.*}}, baseType: ![[ELTTYU8:[0-9]+]]
// CHECK-DAG: ![[ELTTYU8]] = !DIBasicType(name: "__MFloat8_t", size: 8, encoding: DW_ATE_unsigned_char)
__MFloat8_t mfp8;
}
34 changes: 34 additions & 0 deletions clang/test/CodeGen/arm-mfp8.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,39 @@ mfloat8x8_t test_ret_mfloat8x8_t(mfloat8x8_t v) {
return v;
}

// CHECK-C-LABEL: define dso_local <1 x i8> @func1n(
// CHECK-C-SAME: <1 x i8> [[MFP8:%.*]]) #[[ATTR0]] {
// CHECK-C-NEXT: [[ENTRY:.*:]]
// CHECK-C-NEXT: [[MFP8_ADDR:%.*]] = alloca <1 x i8>, align 1
// CHECK-C-NEXT: [[F1N:%.*]] = alloca [10 x <1 x i8>], align 1
// CHECK-C-NEXT: store <1 x i8> [[MFP8]], ptr [[MFP8_ADDR]], align 1
// CHECK-C-NEXT: [[TMP0:%.*]] = load <1 x i8>, ptr [[MFP8_ADDR]], align 1
// CHECK-C-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x <1 x i8>], ptr [[F1N]], i64 0, i64 2
// CHECK-C-NEXT: store <1 x i8> [[TMP0]], ptr [[ARRAYIDX]], align 1
// CHECK-C-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [10 x <1 x i8>], ptr [[F1N]], i64 0, i64 2
// CHECK-C-NEXT: [[TMP1:%.*]] = load <1 x i8>, ptr [[ARRAYIDX1]], align 1
// CHECK-C-NEXT: ret <1 x i8> [[TMP1]]
//
// CHECK-CXX-LABEL: define dso_local <1 x i8> @_Z6func1nu11__MFloat8_t(
// CHECK-CXX-SAME: <1 x i8> [[MFP8:%.*]]) #[[ATTR0]] {
// CHECK-CXX-NEXT: [[ENTRY:.*:]]
// CHECK-CXX-NEXT: [[MFP8_ADDR:%.*]] = alloca <1 x i8>, align 1
// CHECK-CXX-NEXT: [[F1N:%.*]] = alloca [10 x <1 x i8>], align 1
// CHECK-CXX-NEXT: store <1 x i8> [[MFP8]], ptr [[MFP8_ADDR]], align 1
// CHECK-CXX-NEXT: [[TMP0:%.*]] = load <1 x i8>, ptr [[MFP8_ADDR]], align 1
// CHECK-CXX-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x <1 x i8>], ptr [[F1N]], i64 0, i64 2
// CHECK-CXX-NEXT: store <1 x i8> [[TMP0]], ptr [[ARRAYIDX]], align 1
// CHECK-CXX-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [10 x <1 x i8>], ptr [[F1N]], i64 0, i64 2
// CHECK-CXX-NEXT: [[TMP1:%.*]] = load <1 x i8>, ptr [[ARRAYIDX1]], align 1
// CHECK-CXX-NEXT: ret <1 x i8> [[TMP1]]
//
__mfp8 func1n(__mfp8 mfp8) {
__mfp8 f1n[10];
f1n[2] = mfp8;
return f1n[2];
}



//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
// CHECK: {{.*}}
2 changes: 1 addition & 1 deletion clang/test/Modules/no-external-type-id.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export module b;
import a;
export int b();

// CHECK: <DECL_FUNCTION {{.*}} op8=4104
// CHECK: <DECL_FUNCTION {{.*}} op8=4112
// CHECK: <TYPE_FUNCTION_PROTO

//--- a.v1.cppm
Expand Down
11 changes: 11 additions & 0 deletions clang/test/Sema/arm-mfp8.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-arm-none-eabi -target-feature -fp8 %s

// REQUIRES: aarch64-registered-target
#include<arm_neon.h>
__mfp8 test_cast_from_float(unsigned in) {
return (__mfp8)in; // expected-error {{used type '__mfp8' (aka '__MFloat8_t') where arithmetic or pointer type is required}}
}

unsigned test_cast_to_int(__mfp8 in) {
return (unsigned)in; // expected-error {{operand of type '__mfp8' (aka '__MFloat8_t') where arithmetic or pointer type is required}}
}
34 changes: 33 additions & 1 deletion clang/test/Sema/arm-mfp8.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify=sve,neon -triple aarch64-arm-none-eabi \
// RUN: %clang_cc1 -fsyntax-only -verify=sve,neon,scalar -triple aarch64-arm-none-eabi \
// RUN: -target-feature -fp8 -target-feature +sve -target-feature +neon %s

// REQUIRES: aarch64-registered-target
Expand Down Expand Up @@ -29,3 +29,35 @@ void test_vector(mfloat8x8_t a, mfloat8x16_t b, uint8x8_t c) {
c * b; // neon-error {{cannot convert between vector and non-scalar values ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x16_t' (aka '__MFloat8x16_t'))}}
c / b; // neon-error {{cannot convert between vector and non-scalar values ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x16_t' (aka '__MFloat8x16_t'))}}
}
__mfp8 test_static_cast_from_char(char in) {
return static_cast<__mfp8>(in); // scalar-error {{static_cast from 'char' to '__mfp8' (aka '__MFloat8_t') is not allowed}}
}

char test_static_cast_to_char(__mfp8 in) {
return static_cast<char>(in); // scalar-error {{static_cast from '__mfp8' (aka '__MFloat8_t') to 'char' is not allowed}}
}
void test(bool b) {
__mfp8 mfp8;

mfp8 + mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}}
mfp8 - mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}}
mfp8 * mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}}
mfp8 / mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}}
++mfp8; // scalar-error {{cannot increment value of type '__mfp8' (aka '__MFloat8_t')}}
--mfp8; // scalar-error {{cannot decrement value of type '__mfp8' (aka '__MFloat8_t')}}

char u8;

mfp8 + u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}}
u8 + mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}}
mfp8 - u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}}
u8 - mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}}
mfp8 * u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}}
u8 * mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}}
mfp8 / u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}}
u8 / mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}}
mfp8 = u8; // scalar-error {{assigning to '__mfp8' (aka '__MFloat8_t') from incompatible type 'char'}}
u8 = mfp8; // scalar-error {{assigning to 'char' from incompatible type '__mfp8' (aka '__MFloat8_t')}}
mfp8 + (b ? u8 : mfp8); // scalar-error {{incompatible operand types ('char' and '__mfp8' (aka '__MFloat8_t'))}}
}

1 change: 1 addition & 0 deletions clang/utils/TableGen/NeonEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2590,6 +2590,7 @@ void NeonEmitter::runVectorTypes(raw_ostream &OS) {
OS << "#if defined(__aarch64__) || defined(__arm64ec__)\n";
OS << "typedef __MFloat8x8_t mfloat8x8_t;\n";
OS << "typedef __MFloat8x16_t mfloat8x16_t;\n";
OS << "typedef __MFloat8_t __mfp8;\n";
OS << "typedef double float64_t;\n";
OS << "#endif\n\n";

Expand Down

0 comments on commit eb12648

Please sign in to comment.