From cb43021e5726a4462f28a999fb66a8dc20dc354b Mon Sep 17 00:00:00 2001 From: CarolineConcatto Date: Thu, 17 Oct 2024 09:22:55 +0100 Subject: [PATCH] [CLANG]Add Scalable vectors for mfloat8_t (#101644) This patch adds these new vector sizes for sve: svmfloat8_t According to the ARM ACLE PR#323[1]. [1] ARM-software/acle#323 --- .../clang/Basic/AArch64SVEACLETypes.def | 3 ++ clang/include/clang/Basic/arm_sve_sme_incl.td | 1 + .../include/clang/Serialization/ASTBitCodes.h | 2 +- clang/lib/AST/Type.cpp | 1 + clang/test/AST/ast-dump-aarch64-sve-types.c | 3 ++ clang/test/CodeGen/aarch64-sve.c | 2 + .../CodeGenCXX/aarch64-mangle-sve-vectors.cpp | 4 ++ .../test/CodeGenCXX/aarch64-sve-typeinfo.cpp | 5 +++ .../CodeGenCXX/aarch64-sve-vector-init.cpp | 17 ++++++++ clang/test/CodeGenObjC/aarch64-sve-types.m | 3 ++ clang/test/Modules/no-external-type-id.cppm | 2 +- clang/test/Sema/aarch64-sve-types.c | 3 ++ clang/test/Sema/arm-mfp8.cpp | 13 ++++++ clang/test/SemaObjC/aarch64-sve-types.m | 2 + clang/utils/TableGen/SveEmitter.cpp | 41 +++++++++++++++---- 15 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 clang/test/Sema/arm-mfp8.cpp diff --git a/clang/include/clang/Basic/AArch64SVEACLETypes.def b/clang/include/clang/Basic/AArch64SVEACLETypes.def index 55ed9c36f6c5cd..72df1e35aaec20 100644 --- a/clang/include/clang/Basic/AArch64SVEACLETypes.def +++ b/clang/include/clang/Basic/AArch64SVEACLETypes.def @@ -115,6 +115,9 @@ SVE_VECTOR_TYPE_FLOAT("__SVFloat64_t", "__SVFloat64_t", SveFloat64, SveFloat64Ty SVE_VECTOR_TYPE_BFLOAT("__SVBfloat16_t", "__SVBfloat16_t", SveBFloat16, SveBFloat16Ty, 8, 16, 1) +// This is a 8 bits opaque type. +SVE_VECTOR_TYPE_INT("__SVMfloat8_t", "__SVMfloat8_t", SveMFloat8, SveMFloat8Ty, 16, 8, 1, false) + // // x2 // diff --git a/clang/include/clang/Basic/arm_sve_sme_incl.td b/clang/include/clang/Basic/arm_sve_sme_incl.td index fdf4ba55fe9382..50911fb63e818e 100644 --- a/clang/include/clang/Basic/arm_sve_sme_incl.td +++ b/clang/include/clang/Basic/arm_sve_sme_incl.td @@ -162,6 +162,7 @@ def EltTyBool16 : EltType<10>; def EltTyBool32 : EltType<11>; def EltTyBool64 : EltType<12>; def EltTyBFloat16 : EltType<13>; +def EltTyMFloat8 : EltType<14>; class MemEltType { int Value = val; diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 4b79d4b7711905..d735e2dcaa8c56 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -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 = 505; +const unsigned NUM_PREDEF_TYPE_IDS = 506; // Ensure we do not overrun the predefined types we reserved // in the enum PredefinedTypeIDs above. diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index f013ed11d12935..6f23a1a13d0518 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2525,6 +2525,7 @@ bool Type::isSveVLSBuiltinType() const { case BuiltinType::SveBool: case BuiltinType::SveBoolx2: case BuiltinType::SveBoolx4: + case BuiltinType::SveMFloat8: return true; default: return false; diff --git a/clang/test/AST/ast-dump-aarch64-sve-types.c b/clang/test/AST/ast-dump-aarch64-sve-types.c index b5a0b00b492803..386133e05b1d13 100644 --- a/clang/test/AST/ast-dump-aarch64-sve-types.c +++ b/clang/test/AST/ast-dump-aarch64-sve-types.c @@ -45,6 +45,9 @@ // CHECK: TypedefDecl {{.*}} implicit __SVBfloat16_t '__SVBfloat16_t' // CHECK-NEXT: -BuiltinType {{.*}} '__SVBfloat16_t' +// CHECK: TypedefDecl {{.*}} implicit __SVMfloat8_t '__SVMfloat8_t' +// CHECK-NEXT: -BuiltinType {{.*}} '__SVMfloat8_t' + // CHECK: TypedefDecl {{.*}} implicit __SVBool_t '__SVBool_t' // CHECK-NEXT: -BuiltinType {{.*}} '__SVBool_t' diff --git a/clang/test/CodeGen/aarch64-sve.c b/clang/test/CodeGen/aarch64-sve.c index 5f6a0178aa4425..690b010e967ad7 100644 --- a/clang/test/CodeGen/aarch64-sve.c +++ b/clang/test/CodeGen/aarch64-sve.c @@ -13,6 +13,7 @@ // CHECK: %f16 = alloca , align 16 // CHECK: %f32 = alloca , align 16 // CHECK: %f64 = alloca , align 16 +// CHECK: %mf8 = alloca , align 16 // CHECK: %bf16 = alloca , align 16 // CHECK: %b8 = alloca , align 2 @@ -33,6 +34,7 @@ void test_locals(void) { __SVFloat32_t f32; __SVFloat64_t f64; + __SVMfloat8_t mf8; __SVBfloat16_t bf16; __SVBool_t b8; diff --git a/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp b/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp index dfe31ff2ce25fb..3f2b0622d55162 100644 --- a/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp +++ b/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp @@ -17,6 +17,7 @@ void f(__SVFloat16_t, __SVFloat16_t); void f(__SVFloat32_t, __SVFloat32_t); void f(__SVFloat64_t, __SVFloat64_t); void f(__SVBfloat16_t, __SVBfloat16_t); +void f(__SVMfloat8_t, __SVMfloat8_t); void f(__SVBool_t, __SVBool_t); void f(__SVCount_t, __SVCount_t); @@ -150,6 +151,7 @@ void f(__clang_svboolx4_t, __clang_svboolx4_t); // CHECK-NEXT: call void @_Z1fu13__SVFloat16_tS_( zeroinitializer, zeroinitializer) // CHECK-NEXT: call void @_Z1fu13__SVFloat32_tS_( zeroinitializer, zeroinitializer) // CHECK-NEXT: call void @_Z1fu13__SVFloat64_tS_( zeroinitializer, zeroinitializer) +// CHECK-NEXT: call void @_Z1fu13__SVMfloat8_tS_( zeroinitializer, zeroinitializer) // CHECK-NEXT: call void @_Z1fu14__SVBfloat16_tS_( zeroinitializer, zeroinitializer) // CHECK-NEXT: call void @_Z1fu10__SVBool_tS_( zeroinitializer, zeroinitializer) // CHECK-NEXT: call void @_Z1fu11__SVCount_tS_(target("aarch64.svcount") zeroinitializer, target("aarch64.svcount") zeroinitializer) @@ -664,6 +666,7 @@ void f(__clang_svboolx4_t, __clang_svboolx4_t); // COMPAT_17-NEXT: call void @_Z1fu13__SVFloat16_tu13__SVFloat16_t( zeroinitializer, zeroinitializer) // COMPAT_17-NEXT: call void @_Z1fu13__SVFloat32_tu13__SVFloat32_t( zeroinitializer, zeroinitializer) // COMPAT_17-NEXT: call void @_Z1fu13__SVFloat64_tu13__SVFloat64_t( zeroinitializer, zeroinitializer) +// COMPAT_17-NEXT: call void @_Z1fu13__SVMfloat8_tu13__SVMfloat8_t( zeroinitializer, zeroinitializer) // COMPAT_17-NEXT: call void @_Z1fu14__SVBFloat16_tu14__SVBFloat16_t( zeroinitializer, zeroinitializer) // COMPAT_17-NEXT: call void @_Z1fu10__SVBool_tu10__SVBool_t( zeroinitializer, zeroinitializer) // COMPAT_17-NEXT: call void @_Z1fu11__SVCount_tu11__SVCount_t(target("aarch64.svcount") zeroinitializer, target("aarch64.svcount") zeroinitializer) @@ -1100,6 +1103,7 @@ void foo() { f(__SVFloat16_t(), __SVFloat16_t()); f(__SVFloat32_t(), __SVFloat32_t()); f(__SVFloat64_t(), __SVFloat64_t()); + f(__SVMfloat8_t(), __SVMfloat8_t()); f(__SVBfloat16_t(), __SVBfloat16_t()); f(__SVBool_t(), __SVBool_t()); f(__SVCount_t(), __SVCount_t()); diff --git a/clang/test/CodeGenCXX/aarch64-sve-typeinfo.cpp b/clang/test/CodeGenCXX/aarch64-sve-typeinfo.cpp index 7f6b2a9caae6b8..beab9f9078a773 100644 --- a/clang/test/CodeGenCXX/aarch64-sve-typeinfo.cpp +++ b/clang/test/CodeGenCXX/aarch64-sve-typeinfo.cpp @@ -21,6 +21,8 @@ auto &f64 = typeid(__SVFloat64_t); auto &bf16 = typeid(__SVBfloat16_t); +auto &mf8 = typeid(__SVMfloat8_t); + auto &b8 = typeid(__SVBool_t); auto &c8 = typeid(__SVCount_t); @@ -60,6 +62,9 @@ auto &c8 = typeid(__SVCount_t); // CHECK-DAG: @_ZTSu14__SVBfloat16_t = {{.*}} c"u14__SVBfloat16_t\00" // CHECK-DAG: @_ZTIu14__SVBfloat16_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu14__SVBfloat16_t +// CHECK-DAG: @_ZTSu13__SVMfloat8_t = {{.*}} c"u13__SVMfloat8_t\00" +// CHECK-DAG: @_ZTIu13__SVMfloat8_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu13__SVMfloat8_t + // CHECK-DAG: @_ZTSu10__SVBool_t = {{.*}} c"u10__SVBool_t\00" // CHECK-DAG: @_ZTIu10__SVBool_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu10__SVBool_t diff --git a/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp b/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp index 503d77a1822a4b..45cf8081eb3a4d 100644 --- a/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp +++ b/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp @@ -12,6 +12,7 @@ // CHECK-NEXT: [[U16:%.*]] = alloca , align 16 // CHECK-NEXT: [[U32:%.*]] = alloca , align 16 // CHECK-NEXT: [[U64:%.*]] = alloca , align 16 +// CHECK-NEXT: [[MF8:%.*]] = alloca , align 16 // CHECK-NEXT: [[F16:%.*]] = alloca , align 16 // CHECK-NEXT: [[F32:%.*]] = alloca , align 16 // CHECK-NEXT: [[F64:%.*]] = alloca , align 16 @@ -64,6 +65,7 @@ // CHECK-NEXT: store zeroinitializer, ptr [[U16]], align 16 // CHECK-NEXT: store zeroinitializer, ptr [[U32]], align 16 // CHECK-NEXT: store zeroinitializer, ptr [[U64]], align 16 +// CHECK-NEXT: store zeroinitializer, ptr [[MF8]], align 16 // CHECK-NEXT: store zeroinitializer, ptr [[F16]], align 16 // CHECK-NEXT: store zeroinitializer, ptr [[F32]], align 16 // CHECK-NEXT: store zeroinitializer, ptr [[F64]], align 16 @@ -119,6 +121,7 @@ void test_locals(void) { __SVUint16_t u16{}; __SVUint32_t u32{}; __SVUint64_t u64{}; + __SVMfloat8_t mf8{}; __SVFloat16_t f16{}; __SVFloat32_t f32{}; __SVFloat64_t f64{}; @@ -282,6 +285,20 @@ void test_copy_u64(__SVUint64_t a) { __SVUint64_t b{a}; } +// CHECK-LABEL: define dso_local void @_Z13test_copy_mf8u13__SVMfloat8_t +// CHECK-SAME: ( [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca , align 16 +// CHECK-NEXT: [[B:%.*]] = alloca , align 16 +// CHECK-NEXT: store [[A]], ptr [[A_ADDR]], align 16 +// CHECK-NEXT: [[TMP0:%.*]] = load , ptr [[A_ADDR]], align 16 +// CHECK-NEXT: store [[TMP0]], ptr [[B]], align 16 +// CHECK-NEXT: ret void +// +void test_copy_mf8(__SVMfloat8_t a) { + __SVMfloat8_t b{a}; +} + // CHECK-LABEL: define dso_local void @_Z13test_copy_f16u13__SVFloat16_t // CHECK-SAME: ( [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: diff --git a/clang/test/CodeGenObjC/aarch64-sve-types.m b/clang/test/CodeGenObjC/aarch64-sve-types.m index eae734fa4d5931..a97ce4b5bd39f4 100644 --- a/clang/test/CodeGenObjC/aarch64-sve-types.m +++ b/clang/test/CodeGenObjC/aarch64-sve-types.m @@ -31,5 +31,8 @@ // CHECK: error: cannot yet @encode type __SVBfloat16_t const char bf16[] = @encode(__SVBfloat16_t); +// CHECK: error: cannot yet @encode type __SVMfloat8_t +const char mf8[] = @encode(__SVMfloat8_t); + // CHECK: error: cannot yet @encode type __SVBool_t const char b8[] = @encode(__SVBool_t); diff --git a/clang/test/Modules/no-external-type-id.cppm b/clang/test/Modules/no-external-type-id.cppm index 068e52646dcc1c..a4ca389739fbb5 100644 --- a/clang/test/Modules/no-external-type-id.cppm +++ b/clang/test/Modules/no-external-type-id.cppm @@ -23,7 +23,7 @@ export module b; import a; export int b(); -// CHECK: +void test_vector_sve(svmfloat8_t a, svuint8_t c) { + a + c; // sve-error {{cannot convert between vector type 'svuint8_t' (aka '__SVUint8_t') and vector type 'svmfloat8_t' (aka '__SVMfloat8_t') as implicit conversion would cause truncation}} + a - c; // sve-error {{cannot convert between vector type 'svuint8_t' (aka '__SVUint8_t') and vector type 'svmfloat8_t' (aka '__SVMfloat8_t') as implicit conversion would cause truncation}} + a * c; // sve-error {{cannot convert between vector type 'svuint8_t' (aka '__SVUint8_t') and vector type 'svmfloat8_t' (aka '__SVMfloat8_t') as implicit conversion would cause truncation}} + a / c; // sve-error {{cannot convert between vector type 'svuint8_t' (aka '__SVUint8_t') and vector type 'svmfloat8_t' (aka '__SVMfloat8_t') as implicit conversion would cause truncation}} +} + diff --git a/clang/test/SemaObjC/aarch64-sve-types.m b/clang/test/SemaObjC/aarch64-sve-types.m index b50f43cee76f6c..a45e02217667fc 100644 --- a/clang/test/SemaObjC/aarch64-sve-types.m +++ b/clang/test/SemaObjC/aarch64-sve-types.m @@ -20,5 +20,7 @@ @interface foo @property(nullable) __SVBfloat16_t bf16; // expected-error {{cannot be applied to non-pointer type}} +@property(nullable) __SVMfloat8_t mf8; // expected-error {{cannot be applied to non-pointer type}} + @property(nullable) __SVBool_t b8; // expected-error {{cannot be applied to non-pointer type}} @end diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp index 82bbd04f97b4f9..1d79cc71dd977b 100644 --- a/clang/utils/TableGen/SveEmitter.cpp +++ b/clang/utils/TableGen/SveEmitter.cpp @@ -51,7 +51,7 @@ using TypeSpec = std::string; namespace { class SVEType { - bool Float, Signed, Immediate, Void, Constant, Pointer, BFloat; + bool Float, Signed, Immediate, Void, Constant, Pointer, BFloat, MFloat; bool DefaultType, IsScalable, Predicate, PredicatePattern, PrefetchOp, Svcount; unsigned Bitwidth, ElementBitwidth, NumVectors; @@ -61,10 +61,10 @@ class SVEType { SVEType(StringRef TS, char CharMod, unsigned NumVectors = 1) : Float(false), Signed(true), Immediate(false), Void(false), - Constant(false), Pointer(false), BFloat(false), DefaultType(false), - IsScalable(true), Predicate(false), PredicatePattern(false), - PrefetchOp(false), Svcount(false), Bitwidth(128), ElementBitwidth(~0U), - NumVectors(NumVectors) { + Constant(false), Pointer(false), BFloat(false), MFloat(false), + DefaultType(false), IsScalable(true), Predicate(false), + PredicatePattern(false), PrefetchOp(false), Svcount(false), + Bitwidth(128), ElementBitwidth(~0U), NumVectors(NumVectors) { if (!TS.empty()) applyTypespec(TS); applyModifier(CharMod); @@ -82,11 +82,14 @@ class SVEType { bool isVector() const { return NumVectors > 0; } bool isScalableVector() const { return isVector() && IsScalable; } bool isFixedLengthVector() const { return isVector() && !IsScalable; } - bool isChar() const { return ElementBitwidth == 8; } + bool isChar() const { return ElementBitwidth == 8 && !MFloat; } bool isVoid() const { return Void && !Pointer; } bool isDefault() const { return DefaultType; } - bool isFloat() const { return Float && !BFloat; } - bool isBFloat() const { return BFloat && !Float; } + bool isFloat() const { return Float && !BFloat && !MFloat; } + bool isBFloat() const { return BFloat && !Float && !MFloat; } + bool isMFloat() const { + return MFloat && !BFloat && !Float; + } bool isFloatingPoint() const { return Float || BFloat; } bool isInteger() const { return !isFloatingPoint() && !Predicate && !Svcount; @@ -454,6 +457,9 @@ std::string SVEType::builtin_str() const { else if (isBFloat()) { assert(ElementBitwidth == 16 && "Not a valid BFloat."); S += "y"; + } else if (isMFloat()) { + assert(ElementBitwidth == 8 && "Not a valid MFloat."); + S += "m"; } if (!isFloatingPoint()) { @@ -509,6 +515,8 @@ std::string SVEType::str() const { S += "bool"; else if (isBFloat()) S += "bfloat"; + else if (isMFloat()) + S += "mfloat"; else S += "int"; @@ -572,8 +580,16 @@ void SVEType::applyTypespec(StringRef TS) { case 'b': BFloat = true; Float = false; + MFloat = false; ElementBitwidth = 16; break; + case 'm': + Signed = false; + MFloat = true; + Float = false; + BFloat = false; + ElementBitwidth = 8; + break; default: llvm_unreachable("Unhandled type code!"); } @@ -1037,6 +1053,8 @@ std::string Intrinsic::replaceTemplatedArgs(std::string Name, TypeSpec TS, TypeCode = 'b'; else if (T.isBFloat()) TypeCode = "bf"; + else if (T.isMFloat()) + TypeCode = "mfp"; else TypeCode = 'f'; Ret.replace(Pos, NumChars, TypeCode + utostr(T.getElementSizeInBits())); @@ -1130,6 +1148,11 @@ uint64_t SVEEmitter::encodeTypeFlags(const SVEType &T) { return encodeEltType("EltTyBFloat16"); } + if (T.isMFloat()) { + assert(T.getElementSizeInBits() == 8 && "Not a valid MFloat."); + return encodeEltType("EltTyMFloat8"); + } + if (T.isPredicateVector() || T.isSvcount()) { switch (T.getElementSizeInBits()) { case 8: @@ -1305,6 +1328,8 @@ void SVEEmitter::createHeader(raw_ostream &OS) { OS << "#include \n"; OS << "#include \n"; + OS << "typedef __SVMfloat8_t svmfloat8_t;\n\n"; + OS << "typedef __SVFloat32_t svfloat32_t;\n"; OS << "typedef __SVFloat64_t svfloat64_t;\n"; OS << "typedef __clang_svint8x2_t svint8x2_t;\n";