[clang] [CLANG]Add Scalable vectors for mfloat8_t (PR #101644)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 2 02:51:38 PDT 2024
https://github.com/CarolineConcatto created https://github.com/llvm/llvm-project/pull/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
>From de397fb733bfbbe6d8ca14773c02768239bf0a48 Mon Sep 17 00:00:00 2001
From: Caroline Concatto <caroline.concatto at arm.com>
Date: Mon, 24 Jun 2024 09:59:24 +0000
Subject: [PATCH 1/3] [WIP][CLANG][AArch64] Add the modal 8 bit floating-point
scalar type
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.
`mfloat8_t` | equivalent to `__mfp8` |
````
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 fpm8_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.
According to ACLE[1] proposal
[1] https://github.com/ARM-software/acle/pull/323
---
clang/include/clang/AST/ASTContext.h | 1 +
clang/include/clang/AST/BuiltinTypes.def | 4 +
clang/include/clang/AST/Type.h | 5 +
.../clang/Basic/DiagnosticSemaKinds.td | 2 +
clang/include/clang/Basic/Specifiers.h | 1 +
clang/include/clang/Basic/TargetBuiltins.h | 3 +-
clang/include/clang/Basic/TargetInfo.h | 4 +
clang/include/clang/Basic/TokenKinds.def | 1 +
clang/include/clang/Sema/DeclSpec.h | 1 +
.../include/clang/Serialization/ASTBitCodes.h | 5 +-
clang/lib/AST/ASTContext.cpp | 7 ++
clang/lib/AST/ItaniumMangle.cpp | 4 +
clang/lib/AST/PrintfFormatString.cpp | 1 +
clang/lib/AST/Type.cpp | 2 +
clang/lib/AST/TypeLoc.cpp | 1 +
clang/lib/Basic/TargetInfo.cpp | 1 +
clang/lib/Basic/Targets/AArch64.cpp | 6 ++
clang/lib/Basic/Targets/AArch64.h | 3 +
clang/lib/CodeGen/CGDebugInfo.cpp | 1 +
clang/lib/CodeGen/CodeGenModule.cpp | 1 +
clang/lib/CodeGen/CodeGenTypeCache.h | 3 +
clang/lib/CodeGen/CodeGenTypes.cpp | 4 +-
clang/lib/CodeGen/ItaniumCXXABI.cpp | 1 +
clang/lib/Index/USRGeneration.cpp | 1 +
clang/lib/Lex/Lexer.cpp | 1 +
clang/lib/Parse/ParseDecl.cpp | 7 ++
clang/lib/Parse/ParseExpr.cpp | 1 +
clang/lib/Parse/ParseExprCXX.cpp | 3 +
clang/lib/Parse/ParseTentative.cpp | 2 +
clang/lib/Sema/DeclSpec.cpp | 2 +
clang/lib/Sema/SemaCast.cpp | 7 ++
clang/lib/Sema/SemaExpr.cpp | 6 ++
clang/lib/Sema/SemaTemplateVariadic.cpp | 1 +
clang/lib/Sema/SemaType.cpp | 8 +-
clang/lib/Serialization/ASTCommon.cpp | 3 +
clang/lib/Serialization/ASTReader.cpp | 3 +
clang/test/AST/arm-mfp8.cpp | 94 +++++++++++++++++++
clang/test/CodeGen/arm-mfp8.c | 26 +++++
clang/test/Sema/arm-mfp8.c | 11 +++
clang/test/Sema/arm-mfp8.cpp | 35 +++++++
40 files changed, 269 insertions(+), 4 deletions(-)
create mode 100644 clang/test/AST/arm-mfp8.cpp
create mode 100644 clang/test/CodeGen/arm-mfp8.c
create mode 100644 clang/test/Sema/arm-mfp8.c
create mode 100644 clang/test/Sema/arm-mfp8.cpp
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 53ece996769a8..a5f558c735906 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1115,6 +1115,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
CanQualType SatShortFractTy, SatFractTy, SatLongFractTy;
CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy,
SatUnsignedLongFractTy;
+ CanQualType MFloat8Ty;
CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
CanQualType BFloat16Ty;
CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3
diff --git a/clang/include/clang/AST/BuiltinTypes.def b/clang/include/clang/AST/BuiltinTypes.def
index 444be4311a743..3c49852e3f255 100644
--- a/clang/include/clang/AST/BuiltinTypes.def
+++ b/clang/include/clang/AST/BuiltinTypes.def
@@ -221,6 +221,10 @@ FLOATING_TYPE(Float128, Float128Ty)
// '__ibm128'
FLOATING_TYPE(Ibm128, Ibm128Ty)
+
+// '__fpm8'
+UNSIGNED_TYPE(MFloat8, MFloat8Ty)
+
//===- Language-specific types --------------------------------------------===//
// This is the type of C++0x 'nullptr'.
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index fab233b62d8d1..3073391e88cb7 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2492,6 +2492,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool isDoubleType() const;
bool isBFloat16Type() const;
bool isFloat128Type() const;
+ bool isMFloat8Type() const;
bool isIbm128Type() const;
bool isRealType() const; // C99 6.2.5p17 (real floating + integer)
bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating)
@@ -7944,6 +7945,10 @@ inline bool Type::isBFloat16Type() const {
return isSpecificBuiltinType(BuiltinType::BFloat16);
}
+inline bool Type::isMFloat8Type() const {
+ return isSpecificBuiltinType(BuiltinType::MFloat8);
+}
+
inline bool Type::isFloat128Type() const {
return isSpecificBuiltinType(BuiltinType::Float128);
}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8f85371df3b85..af41f65c5e736 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7858,6 +7858,8 @@ def err_bad_lvalue_to_rvalue_cast : Error<
def err_bad_rvalue_to_rvalue_cast : Error<
"cannot cast from rvalue of type %1 to rvalue reference type %2; types are "
"not compatible">;
+def err_bad_mfloat8_cast : Error<
+ "cannot cast %0 to %1; types are not compatible">;
def err_bad_static_cast_pointer_nonpointer : Error<
"cannot cast from type %1 to pointer type %2">;
def err_bad_static_cast_member_pointer_nonmp : Error<
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index fb11e8212f8b6..b5e8dacf63a5c 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -68,6 +68,7 @@ namespace clang {
TST_Accum, // ISO/IEC JTC1 SC22 WG14 N1169 Extension
TST_Fract,
TST_BFloat16,
+ TST_MFloat8,
TST_float,
TST_double,
TST_float128,
diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h
index 4333830bf34f2..6120f54236626 100644
--- a/clang/include/clang/Basic/TargetBuiltins.h
+++ b/clang/include/clang/Basic/TargetBuiltins.h
@@ -198,7 +198,8 @@ namespace clang {
Float16,
Float32,
Float64,
- BFloat16
+ BFloat16,
+ MFloat8
};
NeonTypeFlags(unsigned F) : Flags(F) {}
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 8a6511b9ced83..7671c40d1e81b 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -234,6 +234,7 @@ class TargetInfo : public TransferrableTargetInfo,
bool HasFullBFloat16; // True if the backend supports native bfloat16
// arithmetic. Used to determine excess precision
// support in the frontend.
+ bool HasMFloat8;
bool HasIbm128;
bool HasLongDouble;
bool HasFPReturn;
@@ -700,6 +701,9 @@ class TargetInfo : public TransferrableTargetInfo,
return HasBFloat16 || HasFullBFloat16;
}
+ /// Determine whether the _fpm8 type is supported on this target.
+ virtual bool hasMFloat8Type() const { return HasMFloat8; }
+
/// Determine whether the BFloat type is fully supported on this target, i.e
/// arithemtic operations.
virtual bool hasFullBFloat16Type() const { return HasFullBFloat16; }
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 9c4b17465e18a..9da230fc4f1a3 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -655,6 +655,7 @@ KEYWORD(__bool , KEYALTIVEC|KEYZVECTOR)
// ARM NEON extensions.
ALIAS("__fp16", half , KEYALL)
KEYWORD(__bf16 , KEYALL)
+KEYWORD(__mfp8 , KEYALL)
// OpenCL Extension.
KEYWORD(half , HALFSUPPORT)
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 23bc780e04979..d054320ba7adb 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -287,6 +287,7 @@ class DeclSpec {
static const TST TST_bitint = clang::TST_bitint;
static const TST TST_half = clang::TST_half;
static const TST TST_BFloat16 = clang::TST_BFloat16;
+ static const TST TST_MFloat8 = clang::TST_MFloat8;
static const TST TST_float = clang::TST_float;
static const TST TST_double = clang::TST_double;
static const TST TST_float16 = clang::TST_Float16;
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index a4728b1c06b3f..333aa174567fc 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1078,6 +1078,9 @@ enum PredefinedTypeIDs {
/// \brief The '__ibm128' type
PREDEF_TYPE_IBM128_ID = 74,
+ /// \bried The '__mfp8' type
+ PREDEF_TYPE_MFLOAT8_ID = 75,
+
/// OpenCL image types with auto numeration
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
PREDEF_TYPE_##Id##_ID,
@@ -1109,7 +1112,7 @@ enum PredefinedTypeIDs {
///
/// Type IDs for non-predefined types will start at
/// NUM_PREDEF_TYPE_IDs.
-const unsigned NUM_PREDEF_TYPE_IDS = 503;
+const unsigned NUM_PREDEF_TYPE_IDS = 504;
// Ensure we do not overrun the predefined types we reserved
// in the enum PredefinedTypeIDs above.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 34aa399fda2f8..6cf7b21115a5b 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1408,6 +1408,8 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
// half type (OpenCL 6.1.1.1) / ARM NEON __fp16
InitBuiltinType(HalfTy, BuiltinType::Half);
+ InitBuiltinType(MFloat8Ty, BuiltinType::MFloat8);
+
InitBuiltinType(BFloat16Ty, BuiltinType::BFloat16);
// Builtin type used to help define __builtin_va_list.
@@ -1977,6 +1979,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Target->getBoolWidth();
Align = Target->getBoolAlign();
break;
+ case BuiltinType::MFloat8:
case BuiltinType::Char_S:
case BuiltinType::Char_U:
case BuiltinType::UChar:
@@ -8103,6 +8106,7 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C,
switch (kind) {
case BuiltinType::Void: return 'v';
case BuiltinType::Bool: return 'B';
+ case BuiltinType::MFloat8:
case BuiltinType::Char8:
case BuiltinType::Char_U:
case BuiltinType::UChar: return 'C';
@@ -11466,6 +11470,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
else
Type = Context.CharTy;
break;
+ case 'j':
+ Type = Context.MFloat8Ty;
+ break;
case 'b': // boolean
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!");
Type = Context.BoolTy;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index ed9e6eeb36c75..fe3234ef852fb 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3181,6 +3181,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::SChar:
Out << 'a';
break;
+ case BuiltinType::MFloat8:
case BuiltinType::WChar_S:
case BuiltinType::WChar_U:
Out << 'w';
@@ -3799,6 +3800,7 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
case BuiltinType::Float: EltName = "float32_t"; break;
case BuiltinType::Half: EltName = "float16_t"; break;
case BuiltinType::BFloat16: EltName = "bfloat16_t"; break;
+ case BuiltinType::MFloat8: EltName = "mfloat8_t"; break;
default:
llvm_unreachable("unexpected Neon vector element type");
}
@@ -3852,6 +3854,8 @@ static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) {
return "Float64";
case BuiltinType::BFloat16:
return "Bfloat16";
+ case BuiltinType::MFloat8:
+ return "MFloat8_t";
default:
llvm_unreachable("Unexpected vector element base type");
}
diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp
index dd3b38fabb550..b0180f7554fa1 100644
--- a/clang/lib/AST/PrintfFormatString.cpp
+++ b/clang/lib/AST/PrintfFormatString.cpp
@@ -817,6 +817,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
case BuiltinType::Char32:
case BuiltinType::UInt128:
case BuiltinType::Int128:
+ case BuiltinType::MFloat8:
case BuiltinType::Half:
case BuiltinType::BFloat16:
case BuiltinType::Float16:
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 33acae2cbafac..fdd7872580dc5 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3372,6 +3372,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "unsigned __int128";
case Half:
return Policy.Half ? "half" : "__fp16";
+ case MFloat8:
+ return "__mfp8";
case BFloat16:
return "__bf16";
case Float:
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 9dd90d9bf4e54..531cd4e729332 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -361,6 +361,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::Long:
case BuiltinType::LongLong:
case BuiltinType::Int128:
+ case BuiltinType::MFloat8:
case BuiltinType::Half:
case BuiltinType::Float:
case BuiltinType::Double:
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 29f5cd14e46e1..040b49bb115b8 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -60,6 +60,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
NoAsmVariants = false;
HasLegalHalfType = false;
HalfArgsAndReturns = false;
+ HasMFloat8 = false;
HasFloat128 = false;
HasIbm128 = false;
HasFloat16 = false;
diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 13515699caea4..ef1b05d91f373 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -726,6 +726,7 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
.Case("sha3", HasSHA3)
.Cases("aes", "pmull", HasAES)
.Cases("fp16", "fullfp16", HasFullFP16)
+ .Case("fp8", HasMFloat8)
.Case("dit", HasDIT)
.Case("dpb", HasCCPP)
.Case("dpb2", HasCCDP)
@@ -937,6 +938,9 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
FPU |= NeonMode;
HasSM4 = true;
}
+ if (Feature == "+fp8") {
+ HasMFloat8 = true;
+ }
if (Feature == "+strict-align")
HasUnalignedAccess = false;
@@ -1209,6 +1213,8 @@ bool AArch64TargetInfo::hasBFloat16Type() const {
return true;
}
+bool AArch64TargetInfo::hasMFloat8Type() const { return true; }
+
TargetInfo::CallingConvCheckResult
AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
switch (CC) {
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index 22d7c420d5510..fa3ec2be57d5f 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -47,6 +47,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
bool HasLS64 = false;
bool HasRandGen = false;
bool HasMatMul = false;
+ bool HasMFloat8 = false;
bool HasBFloat16 = false;
bool HasSVE2 = false;
bool HasSVE2AES = false;
@@ -169,6 +170,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
bool hasBFloat16Type() const override;
+ bool hasMFloat8Type() const override;
+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
bool isCLZForZeroUndef() const override;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 572ba84d22ef5..c74bdfa91eb94 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -868,6 +868,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::UChar:
case BuiltinType::Char_U:
+ case BuiltinType::MFloat8:
Encoding = llvm::dwarf::DW_ATE_unsigned_char;
break;
case BuiltinType::Char_S:
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index dd4a665ebc78b..327d926e6d0ac 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -351,6 +351,7 @@ CodeGenModule::CodeGenModule(ASTContext &C,
Int16Ty = llvm::Type::getInt16Ty(LLVMContext);
Int32Ty = llvm::Type::getInt32Ty(LLVMContext);
Int64Ty = llvm::Type::getInt64Ty(LLVMContext);
+ MFloat8Ty = llvm::Type::getInt8Ty(LLVMContext);
HalfTy = llvm::Type::getHalfTy(LLVMContext);
BFloatTy = llvm::Type::getBFloatTy(LLVMContext);
FloatTy = llvm::Type::getFloatTy(LLVMContext);
diff --git a/clang/lib/CodeGen/CodeGenTypeCache.h b/clang/lib/CodeGen/CodeGenTypeCache.h
index e273ebe3b060f..7551fb996827d 100644
--- a/clang/lib/CodeGen/CodeGenTypeCache.h
+++ b/clang/lib/CodeGen/CodeGenTypeCache.h
@@ -38,6 +38,9 @@ struct CodeGenTypeCache {
/// half, bfloat, float, double
llvm::Type *HalfTy, *BFloatTy, *FloatTy, *DoubleTy;
+ /// fpm8 from FP8 is an alias for 8bits data
+ llvm::IntegerType *MFloat8Ty;
+
/// int
llvm::IntegerType *IntTy;
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 0a926e4ac27fe..c6db0a62e56ba 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -419,7 +419,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
Context.getFloatTypeSemantics(T),
/* UseNativeHalf = */ false);
break;
-
+ case BuiltinType::MFloat8:
+ ResultType = llvm::Type::getInt8Ty(getLLVMContext());
+ break;
case BuiltinType::NullPtr:
// Model std::nullptr_t as i8*
ResultType = llvm::PointerType::getUnqual(getLLVMContext());
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 5a3e83de625c9..9ed26119cfdf6 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3387,6 +3387,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
case BuiltinType::BFloat16:
+ case BuiltinType::MFloat8:
return false;
case BuiltinType::Dependent:
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 31c4a3345c09d..1198714cd73f2 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -691,6 +691,7 @@ void USRGenerator::VisitType(QualType T) {
Out << 'v'; break;
case BuiltinType::Bool:
Out << 'b'; break;
+ case BuiltinType::MFloat8:
case BuiltinType::UChar:
Out << 'c'; break;
case BuiltinType::Char8:
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b3862..32ccd0d410a7b 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -97,6 +97,7 @@ bool Token::isSimpleTypeSpecifier(const LangOptions &LangOpts) const {
case tok::kw___bf16:
case tok::kw__Float16:
case tok::kw___float128:
+ case tok::kw___mfp8:
case tok::kw___ibm128:
case tok::kw_wchar_t:
case tok::kw_bool:
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index c528917437332..e7963444ff90a 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4477,6 +4477,10 @@ void Parser::ParseDeclarationSpecifiers(
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,
DiagID, Policy);
break;
+ case tok::kw___mfp8:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_MFloat8, Loc, PrevSpec,
+ DiagID, Policy);
+ break;
case tok::kw_half:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
DiagID, Policy);
@@ -5752,6 +5756,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
case tok::kw__ExtInt:
case tok::kw__BitInt:
case tok::kw___bf16:
+ case tok::kw___mfp8:
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
@@ -5835,6 +5840,7 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw_int:
case tok::kw__ExtInt:
case tok::kw__BitInt:
+ case tok::kw___mfp8:
case tok::kw_half:
case tok::kw___bf16:
case tok::kw_float:
@@ -6057,6 +6063,7 @@ bool Parser::isDeclarationSpecifier(
case tok::kw_int:
case tok::kw__ExtInt:
case tok::kw__BitInt:
+ case tok::kw___mfp8:
case tok::kw_half:
case tok::kw___bf16:
case tok::kw_float:
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index eb7447fa038e4..25c577ab6f871 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1594,6 +1594,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
case tok::kw__BitInt:
case tok::kw_signed:
case tok::kw_unsigned:
+ case tok::kw___mfp8:
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 1d364f77a8146..27b03cb7afd21 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -2405,6 +2405,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
case tok::kw___int128:
DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID, Policy);
break;
+ case tok::kw___mfp8:
+ DS.SetTypeSpecType(DeclSpec::TST_MFloat8, Loc, PrevSpec, DiagID, Policy);
+ break;
case tok::kw___bf16:
DS.SetTypeSpecType(DeclSpec::TST_BFloat16, Loc, PrevSpec, DiagID, Policy);
break;
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index ea17c3e3252ec..bfc64cd8cd04d 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1779,6 +1779,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
case tok::kw_short:
case tok::kw_int:
case tok::kw_long:
+ case tok::kw___mfp8:
case tok::kw___int64:
case tok::kw___int128:
case tok::kw_signed:
@@ -1907,6 +1908,7 @@ bool Parser::isCXXDeclarationSpecifierAType() {
case tok::kw_long:
case tok::kw___int64:
case tok::kw___int128:
+ case tok::kw___mfp8:
case tok::kw_signed:
case tok::kw_unsigned:
case tok::kw_half:
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 60e8189025700..3af64ea55e175 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -358,6 +358,7 @@ bool Declarator::isDeclarationOfFunction() const {
case TST_Fract:
case TST_Float16:
case TST_float128:
+ case TST_MFloat8:
case TST_ibm128:
case TST_enum:
case TST_error:
@@ -575,6 +576,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_fract: return "_Fract";
case DeclSpec::TST_float16: return "_Float16";
case DeclSpec::TST_float128: return "__float128";
+ case DeclSpec::TST_MFloat8: return "__mfp8";
case DeclSpec::TST_ibm128: return "__ibm128";
case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool";
case DeclSpec::TST_decimal32: return "_Decimal32";
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index f03dcf05411df..7348a97dedb32 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -3199,6 +3199,13 @@ void CastOperation::CheckCStyleCast() {
}
}
+ if ((DestType->isMFloat8Type() && !SrcType->isMFloat8Type()) ||
+ (!DestType->isMFloat8Type() && SrcType->isMFloat8Type())) {
+ Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_bad_mfloat8_cast)
+ << SrcType << DestType << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
+ return;
+ }
// ARC imposes extra restrictions on casts.
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) {
checkObjCConversion(CheckedConversionKind::CStyleCast);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 453af8f28f946..9d22be0b9864c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -8512,6 +8512,12 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
return QualType();
}
+ if (LHSTy->isMFloat8Type() || RHSTy->isMFloat8Type()) {
+ Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+ << LHSTy << RHSTy << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
+ }
+
// Diagnose attempts to convert between __ibm128, __float128 and long double
// where such conversions currently can't be handled.
if (unsupportedTypeConversion(*this, LHSTy, RHSTy)) {
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 7a44b978aacdb..c5fcf6bfd7cad 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -908,6 +908,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_char32:
case TST_int:
case TST_int128:
+ case TST_MFloat8:
case TST_half:
case TST_float:
case TST_double:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 441fdcca0758f..4938e568b4a6f 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1134,6 +1134,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) << "__bf16";
Result = Context.BFloat16Ty;
break;
+ case DeclSpec::TST_MFloat8:
+ if (!S.Context.getTargetInfo().hasMFloat8Type())
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) << "__mfp8";
+ Result = Context.MFloat8Ty;
+ break;
case DeclSpec::TST_float: Result = Context.FloatTy; break;
case DeclSpec::TST_double:
if (DS.getTypeSpecWidth() == TypeSpecifierWidth::Long)
@@ -8049,7 +8054,8 @@ static bool isPermittedNeonBaseType(QualType &Ty, VectorKind VecKind, Sema &S) {
BTy->getKind() == BuiltinType::ULongLong ||
BTy->getKind() == BuiltinType::Float ||
BTy->getKind() == BuiltinType::Half ||
- BTy->getKind() == BuiltinType::BFloat16;
+ BTy->getKind() == BuiltinType::BFloat16 ||
+ BTy->getKind() == BuiltinType::MFloat8;
}
static bool verifyValidIntegerConstantExpr(Sema &S, const ParsedAttr &Attr,
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index bc662a87a7bf3..3bc813b4f75d7 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -35,6 +35,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
case BuiltinType::Char_U:
ID = PREDEF_TYPE_CHAR_U_ID;
break;
+ case BuiltinType::MFloat8:
+ ID = PREDEF_TYPE_MFLOAT8_ID;
+ break;
case BuiltinType::UChar:
ID = PREDEF_TYPE_UCHAR_ID;
break;
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index a2c322087fd1e..a15d2f4dd107d 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7197,6 +7197,9 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_INT128_ID:
T = Context.Int128Ty;
break;
+ case PREDEF_TYPE_MFLOAT8_ID:
+ T = Context.MFloat8Ty;
+ break;
case PREDEF_TYPE_BFLOAT16_ID:
T = Context.BFloat16Ty;
break;
diff --git a/clang/test/AST/arm-mfp8.cpp b/clang/test/AST/arm-mfp8.cpp
new file mode 100644
index 0000000000000..d99b7cd062e30
--- /dev/null
+++ b/clang/test/AST/arm-mfp8.cpp
@@ -0,0 +1,94 @@
+// 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. */
+
+/* Namespace */
+namespace {
+ __mfp8 f2n;
+ __mfp8 arr1n[10];
+}
+
+//CHECK: |-NamespaceDecl {{.*}}
+//CHECK-NEXT: | |-VarDecl {{.*}} f2n '__mfp8'
+//CHECK-NEXT: | `-VarDecl {{.*}} arr1n '__mfp8[10]'
+
+ __mfp8 arr1[10];
+ //__mfp8 arr2n[] { 1, 3, 3 }; cannot initialize
+
+ const __mfp8 func1n(const __mfp8 mfp8) {
+ // this should fail
+ __mfp8 f1n;
+ f1n = mfp8;
+ return f1n;
+ }
+
+//CHECK: |-VarDecl {{.*}} '__mfp8[10]'
+
+//CHECK: | `-VarDecl {{.*}} f1n '__mfp8'
+//CHECK-NEXT: |-BinaryOperator {{.*}} '__mfp8' lvalue '='
+//CHECK-NEXT: | |-DeclRefExpr {{.*}} '__mfp8' lvalue Var {{.*}} 'f1n' '__mfp8'
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8' <LValueToRValue>
+//CHECK-NEXT: | `-DeclRefExpr {{.*}} 'const __mfp8' lvalue ParmVar {{.*}} 'mfp8' 'const __mfp8'
+//CHECK-NEXT: `-ReturnStmt {{.*}}
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '__mfp8' <LValueToRValue>
+//CHECK-NEXT: `-DeclRefExpr {{.*}} '__mfp8' lvalue Var {{.*}} 'f1n' '__mfp8'
+
+
+/* Class */
+
+class C1 {
+ __mfp8 f1c;
+ static const __mfp8 f2c;
+ volatile __mfp8 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'
+//CHECK-NEXT: | |-VarDecl {{.*}} f2c 'const __mfp8' static
+//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile __mfp8'
+//CHECK-NEXT: | |-AccessSpecDecl {{.*}}
+//CHECK-NEXT: | |-CXXConstructorDecl {{.*}} C1 'void (__mfp8)' implicit-inline
+//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8'
+//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f1c' '__mfp8'
+//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8' <LValueToRValue>
+//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8' lvalue ParmVar {{.*}} 'arg' '__mfp8'
+//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f3c' 'volatile __mfp8'
+//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8' <LValueToRValue>
+//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8' lvalue ParmVar {{.*}} 'arg' '__mfp8'
+//CHECK-NEXT: | | `-CompoundStmt {{.*}}
+//CHECK-NEXT: | |-CXXMethodDecl {{.*}} func1c '__mfp8 (__mfp8)' implicit-inline
+//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8'
+//CHECK-NEXT: | | `-CompoundStmt {{.*}}
+//CHECK-NEXT: | | `-ReturnStmt {{.*}}
+//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '__mfp8' <LValueToRValue>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '__mfp8' lvalue ParmVar {{.*}}8 'arg' '__mfp8'
+//CHECK-NEXT: | `-CXXMethodDecl {{.*}} func2c '__mfp8 (__mfp8)' static implicit-inline
+//CHECK-NEXT: | |-ParmVarDecl {{.*}} arg '__mfp8'
+//CHECK-NEXT: | `-CompoundStmt {{.*}}
+//CHECK-NEXT: | `-ReturnStmt {{.*}}
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8' <LValueToRValue>
+//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__mfp8' lvalue ParmVar {{.*}} 'arg' '__mfp8'
+
+template <class C> struct S1 {
+ C mem1;
+};
+
+template <> struct S1<__mfp8> {
+ __mfp8 mem2;
+};
+
+//CHECK: |-TemplateArgument type '__mfp8'
+//CHECK-NEXT: | `-BuiltinType {{.*}} '__mfp8'
+//CHECK-NEXT: |-CXXRecordDecl {{.*}} implicit struct S1
+//CHECK-NEXT: `-FieldDecl {{.*}} mem2 '__mfp8'
diff --git a/clang/test/CodeGen/arm-mfp8.c b/clang/test/CodeGen/arm-mfp8.c
new file mode 100644
index 0000000000000..c32410d458519
--- /dev/null
+++ b/clang/test/CodeGen/arm-mfp8.c
@@ -0,0 +1,26 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// RUN: %clang_cc1 -emit-llvm -triple aarch64-arm-none-eabi -target-feature -fp8 -o - %s | FileCheck %s
+
+// REQUIRES: aarch64-registered-target
+
+// CHECK-LABEL: define dso_local i8 @func1n(
+// CHECK-SAME: i8 noundef [[MFP8:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[MFP8_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT: [[F1N:%.*]] = alloca [10 x i8], align 1
+// CHECK-NEXT: store i8 [[MFP8]], ptr [[MFP8_ADDR]], align 1
+// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[MFP8_ADDR]], align 1
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
+// CHECK-NEXT: store i8 [[TMP0]], ptr [[ARRAYIDX]], align 1
+// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
+// CHECK-NEXT: ret i8 [[TMP1]]
+//
+__mfp8 func1n(__mfp8 mfp8) {
+ __mfp8 f1n[10];
+ f1n[2] = mfp8;
+ return f1n[2];
+}
+
+
+
diff --git a/clang/test/Sema/arm-mfp8.c b/clang/test/Sema/arm-mfp8.c
new file mode 100644
index 0000000000000..c1e74a18b647d
--- /dev/null
+++ b/clang/test/Sema/arm-mfp8.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-arm-none-eabi -target-feature -fp8 %s
+
+// REQUIRES: aarch64-registered-target
+
+__mfp8 test_cast_from_float(unsigned in) {
+ return (__mfp8)in; // expected-error {{cannot cast 'unsigned int' to '__mfp8'; types are not compatible}}
+}
+
+unsigned test_cast_to_int(__mfp8 in) {
+ return (unsigned)in; // expected-error {{cannot cast '__mfp8' to 'unsigned int'; types are not compatible}}
+}
diff --git a/clang/test/Sema/arm-mfp8.cpp b/clang/test/Sema/arm-mfp8.cpp
new file mode 100644
index 0000000000000..d9e03dc0e3f0d
--- /dev/null
+++ b/clang/test/Sema/arm-mfp8.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=scalar -triple aarch64-arm-none-eabi -target-feature -fp8 %s
+
+// REQUIRES: aarch64-registered-target
+__mfp8 test_static_cast_from_char(char in) {
+ return static_cast<__mfp8>(in); // scalar-error {{static_cast from 'char' to '__mfp8' is not allowed}}
+}
+
+char test_static_cast_to_char(__mfp8 in) {
+ return static_cast<char>(in); // scalar-error {{static_cast from '__mfp8' to 'char' is not allowed}}
+}
+void test(bool b) {
+ __mfp8 mfp8;
+
+ mfp8 + mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' and '__mfp8')}}
+ mfp8 - mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' and '__mfp8')}}
+ mfp8 * mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' and '__mfp8')}}
+ mfp8 / mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' and '__mfp8')}}
+ ++mfp8; // scalar-error {{cannot increment value of type '__mfp8'}}
+ --mfp8; // scalar-error {{cannot decrement value of type '__mfp8'}}
+
+ char u8;
+
+ mfp8 + u8; // scalar-error {{invalid operands to binary expression ('__mfp8' and 'char')}}
+ u8 + mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8')}}
+ mfp8 - u8; // scalar-error {{invalid operands to binary expression ('__mfp8' and 'char')}}
+ u8 - mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8')}}
+ mfp8 * u8; // scalar-error {{invalid operands to binary expression ('__mfp8' and 'char')}}
+ u8 * mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8')}}
+ mfp8 / u8; // scalar-error {{invalid operands to binary expression ('__mfp8' and 'char')}}
+ u8 / mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8')}}
+ mfp8 = u8; // scalar-error {{assigning to '__mfp8' from incompatible type 'char'}}
+ u8 = mfp8; // scalar-error {{assigning to 'char' from incompatible type '__mfp8'}}
+ mfp8 + (b ? u8 : mfp8); // scalar-error {{incompatible operand types ('char' and '__mfp8')}}
+}
+
>From bfd90a75a0ff286b10f003dc0e423fd3853a9d46 Mon Sep 17 00:00:00 2001
From: Caroline Concatto <caroline.concatto at arm.com>
Date: Fri, 19 Jul 2024 09:10:57 +0000
Subject: [PATCH 2/3] [CLANG]Add Neon vectors for mfloat8_t
This patch adds these new vector sizes for neon:
mfloat8x16_t and mfloat8x8_t
According to the ARM ACLE PR#323[1].
[1] ARM-software/acle#323
---
clang/include/clang/Basic/arm_mfp8.td | 14 ++++
clang/include/clang/Basic/arm_neon_incl.td | 2 +
clang/lib/Basic/Targets/AArch64.cpp | 3 +
clang/lib/Basic/Targets/ARM.cpp | 2 +
clang/lib/Basic/Targets/ARM.h | 2 +
clang/lib/CodeGen/CGBuiltin.cpp | 2 +
clang/lib/Headers/CMakeLists.txt | 3 +
clang/lib/Sema/SemaARM.cpp | 2 +
clang/lib/Sema/SemaExpr.cpp | 5 ++
clang/test/CodeGen/arm-mfp8.c | 85 ++++++++++++++++++----
clang/test/Sema/arm-fpm8.cpp | 53 ++++++++++++++
clang/test/Sema/arm-mfp8.cpp | 20 ++++-
clang/utils/TableGen/NeonEmitter.cpp | 58 ++++++++++++++-
clang/utils/TableGen/TableGen.cpp | 5 ++
clang/utils/TableGen/TableGenBackends.h | 1 +
15 files changed, 240 insertions(+), 17 deletions(-)
create mode 100644 clang/include/clang/Basic/arm_mfp8.td
create mode 100644 clang/test/Sema/arm-fpm8.cpp
diff --git a/clang/include/clang/Basic/arm_mfp8.td b/clang/include/clang/Basic/arm_mfp8.td
new file mode 100644
index 0000000000000..9c91cd1060494
--- /dev/null
+++ b/clang/include/clang/Basic/arm_mfp8.td
@@ -0,0 +1,14 @@
+//===--- arm_mfp8.td - ARM MFP8 compiler interface ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TableGen definitions from which the ARM MFP8 header
+// file will be generated.
+//
+//===----------------------------------------------------------------------===//
+
+include "arm_neon_incl.td"
diff --git a/clang/include/clang/Basic/arm_neon_incl.td b/clang/include/clang/Basic/arm_neon_incl.td
index b8155c187d1bc..ab0a3b621dd67 100644
--- a/clang/include/clang/Basic/arm_neon_incl.td
+++ b/clang/include/clang/Basic/arm_neon_incl.td
@@ -216,6 +216,7 @@ def OP_UNAVAILABLE : Operation {
// h: half-float
// d: double
// b: bfloat16
+// m: mfloat8
//
// Typespec modifiers
// ------------------
@@ -240,6 +241,7 @@ def OP_UNAVAILABLE : Operation {
// B: change to BFloat16
// P: change to polynomial category.
// p: change polynomial to equivalent integer category. Otherwise nop.
+// M: change to MFloat8.
//
// >: double element width (vector size unchanged).
// <: half element width (vector size unchanged).
diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index ef1b05d91f373..f3165b256cbc1 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -543,6 +543,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", "1");
}
+ if (HasMFloat8) {
+ Builder.defineMacro("__ARM_FEATURE_FP8", "1");
+ }
if ((FPU & SveMode) && HasBFloat16) {
Builder.defineMacro("__ARM_FEATURE_SVE_BF16", "1");
}
diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp
index 7423626d7c3cb..7209b66680cba 100644
--- a/clang/lib/Basic/Targets/ARM.cpp
+++ b/clang/lib/Basic/Targets/ARM.cpp
@@ -661,6 +661,8 @@ bool ARMTargetInfo::hasBFloat16Type() const {
return HasBFloat16 || (FPU && !SoftFloat);
}
+bool ARMTargetInfo::hasMFloat8Type() const { return true; }
+
bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
return Name == "generic" ||
llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;
diff --git a/clang/lib/Basic/Targets/ARM.h b/clang/lib/Basic/Targets/ARM.h
index df9855a52e61c..b1104fe3862a6 100644
--- a/clang/lib/Basic/Targets/ARM.h
+++ b/clang/lib/Basic/Targets/ARM.h
@@ -176,6 +176,8 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
bool hasBFloat16Type() const override;
+ bool hasMFloat8Type() const override;
+
bool isValidCPUName(StringRef Name) const override;
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 511e1fd4016d7..ab767124a4bba 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -6230,6 +6230,8 @@ static llvm::FixedVectorType *GetNeonType(CodeGenFunction *CGF,
case NeonTypeFlags::Int8:
case NeonTypeFlags::Poly8:
return llvm::FixedVectorType::get(CGF->Int8Ty, V1Ty ? 1 : (8 << IsQuad));
+ case NeonTypeFlags::MFloat8:
+ return llvm::FixedVectorType::get(CGF->MFloat8Ty, V1Ty ? 1 : (8 << IsQuad));
case NeonTypeFlags::Int16:
case NeonTypeFlags::Poly16:
return llvm::FixedVectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index d3090e488306f..1033e1c31ab3f 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -391,6 +391,8 @@ if(ARM IN_LIST LLVM_TARGETS_TO_BUILD OR AArch64 IN_LIST LLVM_TARGETS_TO_BUILD)
clang_generate_header(-gen-arm-sme-header arm_sme.td arm_sme.h)
# Generate arm_bf16.h
clang_generate_header(-gen-arm-bf16 arm_bf16.td arm_bf16.h)
+ # Generate arm_mfp8.h
+ clang_generate_header(-gen-arm-mfp8 arm_mfp8.td arm_mfp8.h)
# Generate arm_mve.h
clang_generate_header(-gen-arm-mve-header arm_mve.td arm_mve.h)
# Generate arm_cde.h
@@ -414,6 +416,7 @@ if(ARM IN_LIST LLVM_TARGETS_TO_BUILD OR AArch64 IN_LIST LLVM_TARGETS_TO_BUILD)
"${CMAKE_CURRENT_BINARY_DIR}/arm_sme.h"
"${CMAKE_CURRENT_BINARY_DIR}/arm_bf16.h"
"${CMAKE_CURRENT_BINARY_DIR}/arm_vector_types.h"
+ "${CMAKE_CURRENT_BINARY_DIR}/arm_mfp8.h"
)
endif()
if(RISCV IN_LIST LLVM_TARGETS_TO_BUILD)
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 281d534152054..839ebbe45e536 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -385,6 +385,8 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
return Context.DoubleTy;
case NeonTypeFlags::BFloat16:
return Context.BFloat16Ty;
+ case NeonTypeFlags::MFloat8:
+ return Context.MFloat8Ty;
}
llvm_unreachable("Invalid NeonTypeFlag!");
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9d22be0b9864c..3881dad5eb791 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -10215,6 +10215,11 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
const VectorType *RHSVecType = RHSType->getAs<VectorType>();
assert(LHSVecType || RHSVecType);
+ // Any operation with MFloat8 type is only possible with C intrinsics
+ if ((LHSVecType && LHSVecType->getElementType()->isMFloat8Type()) ||
+ (RHSVecType && RHSVecType->getElementType()->isMFloat8Type()))
+ return InvalidOperands(Loc, LHS, RHS);
+
// AltiVec-style "vector bool op vector bool" combinations are allowed
// for some operators but not others.
if (!AllowBothBool && LHSVecType &&
diff --git a/clang/test/CodeGen/arm-mfp8.c b/clang/test/CodeGen/arm-mfp8.c
index c32410d458519..48201608d2b2b 100644
--- a/clang/test/CodeGen/arm-mfp8.c
+++ b/clang/test/CodeGen/arm-mfp8.c
@@ -1,20 +1,34 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
-// RUN: %clang_cc1 -emit-llvm -triple aarch64-arm-none-eabi -target-feature -fp8 -o - %s | FileCheck %s
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -emit-llvm -triple aarch64-arm-none-eabi -target-feature -fp8 -target-feature +neon -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-C
+// RUN: %clang_cc1 -emit-llvm -triple aarch64-arm-none-eabi -target-feature -fp8 -target-feature +neon -o - -x c++ %s | FileCheck %s --check-prefixes=CHECK,CHECK-CXX
// REQUIRES: aarch64-registered-target
-// CHECK-LABEL: define dso_local i8 @func1n(
-// CHECK-SAME: i8 noundef [[MFP8:%.*]]) #[[ATTR0:[0-9]+]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[MFP8_ADDR:%.*]] = alloca i8, align 1
-// CHECK-NEXT: [[F1N:%.*]] = alloca [10 x i8], align 1
-// CHECK-NEXT: store i8 [[MFP8]], ptr [[MFP8_ADDR]], align 1
-// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[MFP8_ADDR]], align 1
-// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
-// CHECK-NEXT: store i8 [[TMP0]], ptr [[ARRAYIDX]], align 1
-// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
-// CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
-// CHECK-NEXT: ret i8 [[TMP1]]
+// CHECK-C-LABEL: define dso_local i8 @func1n(
+// CHECK-C-SAME: i8 noundef [[MFP8:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-C-NEXT: [[ENTRY:.*:]]
+// CHECK-C-NEXT: [[MFP8_ADDR:%.*]] = alloca i8, align 1
+// CHECK-C-NEXT: [[F1N:%.*]] = alloca [10 x i8], align 1
+// CHECK-C-NEXT: store i8 [[MFP8]], ptr [[MFP8_ADDR]], align 1
+// CHECK-C-NEXT: [[TMP0:%.*]] = load i8, ptr [[MFP8_ADDR]], align 1
+// CHECK-C-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
+// CHECK-C-NEXT: store i8 [[TMP0]], ptr [[ARRAYIDX]], align 1
+// CHECK-C-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
+// CHECK-C-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
+// CHECK-C-NEXT: ret i8 [[TMP1]]
+//
+// CHECK-CXX-LABEL: define dso_local noundef i8 @_Z6func1nw(
+// CHECK-CXX-SAME: i8 noundef [[MFP8:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[MFP8_ADDR:%.*]] = alloca i8, align 1
+// CHECK-CXX-NEXT: [[F1N:%.*]] = alloca [10 x i8], align 1
+// CHECK-CXX-NEXT: store i8 [[MFP8]], ptr [[MFP8_ADDR]], align 1
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = load i8, ptr [[MFP8_ADDR]], align 1
+// CHECK-CXX-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
+// CHECK-CXX-NEXT: store i8 [[TMP0]], ptr [[ARRAYIDX]], align 1
+// CHECK-CXX-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [10 x i8], ptr [[F1N]], i64 0, i64 2
+// CHECK-CXX-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
+// CHECK-CXX-NEXT: ret i8 [[TMP1]]
//
__mfp8 func1n(__mfp8 mfp8) {
__mfp8 f1n[10];
@@ -23,4 +37,47 @@ __mfp8 func1n(__mfp8 mfp8) {
}
+#include <arm_neon.h>
+
+// CHECK-C-LABEL: define dso_local <16 x i8> @test_ret_mfloat8x16_t(
+// CHECK-C-SAME: <16 x i8> noundef [[V:%.*]]) #[[ATTR0]] {
+// CHECK-C-NEXT: [[ENTRY:.*:]]
+// CHECK-C-NEXT: [[V_ADDR:%.*]] = alloca <16 x i8>, align 16
+// CHECK-C-NEXT: store <16 x i8> [[V]], ptr [[V_ADDR]], align 16
+// CHECK-C-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[V_ADDR]], align 16
+// CHECK-C-NEXT: ret <16 x i8> [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local noundef <16 x i8> @_Z21test_ret_mfloat8x16_t16__MFloat8_tx16_t(
+// CHECK-CXX-SAME: <16 x i8> noundef [[V:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[V_ADDR:%.*]] = alloca <16 x i8>, align 16
+// CHECK-CXX-NEXT: store <16 x i8> [[V]], ptr [[V_ADDR]], align 16
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[V_ADDR]], align 16
+// CHECK-CXX-NEXT: ret <16 x i8> [[TMP0]]
+//
+mfloat8x16_t test_ret_mfloat8x16_t(mfloat8x16_t v) {
+ return v;
+}
+
+// CHECK-C-LABEL: define dso_local <8 x i8> @test_ret_mfloat8x8_t(
+// CHECK-C-SAME: <8 x i8> noundef [[V:%.*]]) #[[ATTR0]] {
+// CHECK-C-NEXT: [[ENTRY:.*:]]
+// CHECK-C-NEXT: [[V_ADDR:%.*]] = alloca <8 x i8>, align 8
+// CHECK-C-NEXT: store <8 x i8> [[V]], ptr [[V_ADDR]], align 8
+// CHECK-C-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[V_ADDR]], align 8
+// CHECK-C-NEXT: ret <8 x i8> [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local noundef <8 x i8> @_Z20test_ret_mfloat8x8_t15__MFloat8_tx8_t(
+// CHECK-CXX-SAME: <8 x i8> noundef [[V:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[V_ADDR:%.*]] = alloca <8 x i8>, align 8
+// CHECK-CXX-NEXT: store <8 x i8> [[V]], ptr [[V_ADDR]], align 8
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[V_ADDR]], align 8
+// CHECK-CXX-NEXT: ret <8 x i8> [[TMP0]]
+//
+mfloat8x8_t test_ret_mfloat8x8_t(mfloat8x8_t v) {
+ return v;
+}
+//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+// CHECK: {{.*}}
diff --git a/clang/test/Sema/arm-fpm8.cpp b/clang/test/Sema/arm-fpm8.cpp
new file mode 100644
index 0000000000000..63eff13f1e290
--- /dev/null
+++ b/clang/test/Sema/arm-fpm8.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=scalar,neon -triple aarch64-arm-none-eabi \
+// RUN: -target-feature -fp8 -target-feature +neon %s
+
+// REQUIRES: aarch64-registered-target
+__fpm8 test_static_cast_from_char(char in) {
+ return static_cast<__fpm8>(in); // scalar-error {{static_cast from 'char' to '__fpm8' is not allowed}}
+}
+
+char test_static_cast_to_char(__fpm8 in) {
+ return static_cast<char>(in); // scalar-error {{static_cast from '__fpm8' to 'char' is not allowed}}
+}
+void test(bool b) {
+ __fpm8 fpm8;
+
+ fpm8 + fpm8; // scalar-error {{invalid operands to binary expression ('__fpm8' and '__fpm8')}}
+ fpm8 - fpm8; // scalar-error {{invalid operands to binary expression ('__fpm8' and '__fpm8')}}
+ fpm8 * fpm8; // scalar-error {{invalid operands to binary expression ('__fpm8' and '__fpm8')}}
+ fpm8 / fpm8; // scalar-error {{invalid operands to binary expression ('__fpm8' and '__fpm8')}}
+ ++fpm8; // scalar-error {{cannot increment value of type '__fpm8'}}
+ --fpm8; // scalar-error {{cannot decrement value of type '__fpm8'}}
+
+ char u8;
+
+ fpm8 + u8; // scalar-error {{invalid operands to binary expression ('__fpm8' and 'char')}}
+ u8 + fpm8; // scalar-error {{invalid operands to binary expression ('char' and '__fpm8')}}
+ fpm8 - u8; // scalar-error {{invalid operands to binary expression ('__fpm8' and 'char')}}
+ u8 - fpm8; // scalar-error {{invalid operands to binary expression ('char' and '__fpm8')}}
+ fpm8 * u8; // scalar-error {{invalid operands to binary expression ('__fpm8' and 'char')}}
+ u8 * fpm8; // scalar-error {{invalid operands to binary expression ('char' and '__fpm8')}}
+ fpm8 / u8; // scalar-error {{invalid operands to binary expression ('__fpm8' and 'char')}}
+ u8 / fpm8; // scalar-error {{invalid operands to binary expression ('char' and '__fpm8')}}
+ fpm8 = u8; // scalar-error {{assigning to '__fpm8' from incompatible type 'char'}}
+ u8 = fpm8; // scalar-error {{assigning to 'char' from incompatible type '__fpm8'}}
+ fpm8 + (b ? u8 : fpm8); // scalar-error {{incompatible operand types ('char' and '__fpm8')}}
+}
+
+#include <arm_neon.h>
+
+void test_vector(fpm8x8_t a, fpm8x8_t b, uint8x8_t c) {
+ a + b; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'fpm8x8_t')}}
+ a - b; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'fpm8x8_t')}}
+ a * b; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'fpm8x8_t')}}
+ a / b; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'fpm8x8_t')}}
+
+ a + c; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
+ a - c; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
+ a * c; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
+ a / c; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
+ c + b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'fpm8x8_t' (vector of 8 'fpm8_t' values))}}
+ c - b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'fpm8x8_t' (vector of 8 'fpm8_t' values))}}
+ c * b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'fpm8x8_t' (vector of 8 'fpm8_t' values))}}
+ c / b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'fpm8x8_t' (vector of 8 'fpm8_t' values))}}
+}
diff --git a/clang/test/Sema/arm-mfp8.cpp b/clang/test/Sema/arm-mfp8.cpp
index d9e03dc0e3f0d..7a697f7b35274 100644
--- a/clang/test/Sema/arm-mfp8.cpp
+++ b/clang/test/Sema/arm-mfp8.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=scalar -triple aarch64-arm-none-eabi -target-feature -fp8 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=scalar,neon -triple aarch64-arm-none-eabi \
+// RUN: -target-feature -fp8 -target-feature +neon %s
// REQUIRES: aarch64-registered-target
__mfp8 test_static_cast_from_char(char in) {
@@ -33,3 +34,20 @@ void test(bool b) {
mfp8 + (b ? u8 : mfp8); // scalar-error {{incompatible operand types ('char' and '__mfp8')}}
}
+#include <arm_neon.h>
+
+void test_vector(mfloat8x8_t a, mfloat8x8_t b, uint8x8_t c) {
+ a + b; // neon-error {{invalid operands to binary expression ('mfloat8x8_t' (vector of 8 'mfloat8_t' values) and 'mfloat8x8_t')}}
+ a - b; // neon-error {{invalid operands to binary expression ('mfloat8x8_t' (vector of 8 'mfloat8_t' values) and 'mfloat8x8_t')}}
+ a * b; // neon-error {{invalid operands to binary expression ('mfloat8x8_t' (vector of 8 'mfloat8_t' values) and 'mfloat8x8_t')}}
+ a / b; // neon-error {{invalid operands to binary expression ('mfloat8x8_t' (vector of 8 'mfloat8_t' values) and 'mfloat8x8_t')}}
+
+ a + c; // neon-error {{invalid operands to binary expression ('mfloat8x8_t' (vector of 8 'mfloat8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
+ a - c; // neon-error {{invalid operands to binary expression ('mfloat8x8_t' (vector of 8 'mfloat8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
+ a * c; // neon-error {{invalid operands to binary expression ('mfloat8x8_t' (vector of 8 'mfloat8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
+ a / c; // neon-error {{invalid operands to binary expression ('mfloat8x8_t' (vector of 8 'mfloat8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
+ c + b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x8_t' (vector of 8 'mfloat8_t' values))}}
+ c - b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x8_t' (vector of 8 'mfloat8_t' values))}}
+ c * b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x8_t' (vector of 8 'mfloat8_t' values))}}
+ c / b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x8_t' (vector of 8 'mfloat8_t' values))}}
+}
diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp
index 56f1fdf9ef574..1db1074270102 100644
--- a/clang/utils/TableGen/NeonEmitter.cpp
+++ b/clang/utils/TableGen/NeonEmitter.cpp
@@ -99,7 +99,8 @@ enum EltType {
Float16,
Float32,
Float64,
- BFloat16
+ BFloat16,
+ MFloat8
};
} // end namespace NeonTypeFlags
@@ -148,6 +149,7 @@ class Type {
UInt,
Poly,
BFloat16,
+ MFloat8,
};
TypeKind Kind;
bool Immediate, Constant, Pointer;
@@ -201,6 +203,7 @@ class Type {
bool isLong() const { return isInteger() && ElementBitwidth == 64; }
bool isVoid() const { return Kind == Void; }
bool isBFloat16() const { return Kind == BFloat16; }
+ bool isMFloat8() const { return Kind == MFloat8; }
unsigned getNumElements() const { return Bitwidth / ElementBitwidth; }
unsigned getSizeInBits() const { return Bitwidth; }
unsigned getElementSizeInBits() const { return ElementBitwidth; }
@@ -595,6 +598,8 @@ class NeonEmitter {
// Emit arm_bf16.h.inc
void runBF16(raw_ostream &o);
+ void runMFloat8(raw_ostream &o);
+
void runVectorTypes(raw_ostream &o);
// Emit all the __builtin prototypes used in arm_neon.h, arm_fp16.h and
@@ -622,6 +627,8 @@ std::string Type::str() const {
S += "float";
else if (isBFloat16())
S += "bfloat";
+ else if (isMFloat8())
+ S += "mfloat";
else
S += "int";
@@ -664,6 +671,8 @@ std::string Type::builtin_str() const {
else if (isBFloat16()) {
assert(ElementBitwidth == 16 && "BFloat16 can only be 16 bits");
S += "y";
+ } else if (isMFloat8()) {
+ S += "c";
} else
switch (ElementBitwidth) {
case 16: S += "h"; break;
@@ -718,6 +727,11 @@ unsigned Type::getNeonEnum() const {
Base = (unsigned)NeonTypeFlags::Float16 + (Addend - 1);
}
+ if (isMFloat8()) {
+ assert(Addend == 1 && "MFloat8 is only 8 bit");
+ Base = (unsigned)NeonTypeFlags::MFloat8;
+ }
+
if (isBFloat16()) {
assert(Addend == 1 && "BFloat16 is only 16 bit");
Base = (unsigned)NeonTypeFlags::BFloat16;
@@ -744,6 +758,8 @@ Type Type::fromTypedefName(StringRef Name) {
T.Kind = Poly;
} else if (Name.consume_front("bfloat")) {
T.Kind = BFloat16;
+ } else if (Name.consume_front("mfp")) {
+ T.Kind = MFloat8;
} else {
assert(Name.starts_with("int"));
Name = Name.drop_front(3);
@@ -840,6 +856,10 @@ void Type::applyTypespec(bool &Quad) {
if (isPoly())
NumVectors = 0;
break;
+ case 'm':
+ Kind = MFloat8;
+ ElementBitwidth = 8;
+ break;
case 'b':
Kind = BFloat16;
ElementBitwidth = 16;
@@ -874,6 +894,10 @@ void Type::applyModifiers(StringRef Mods) {
Kind = BFloat16;
ElementBitwidth = 16;
break;
+ case 'M':
+ Kind = MFloat8;
+ ElementBitwidth = 8;
+ break;
case 'F':
Kind = Float;
break;
@@ -958,6 +982,9 @@ std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const {
if (T.isBFloat16())
return "bf16";
+ if (T.isMFloat8())
+ return "mfp8";
+
if (T.isPoly())
typeCode = 'p';
else if (T.isInteger())
@@ -995,7 +1022,7 @@ std::string Intrinsic::getBuiltinTypeStr() {
Type RetT = getReturnType();
if ((LocalCK == ClassI || LocalCK == ClassW) && RetT.isScalar() &&
- !RetT.isFloating() && !RetT.isBFloat16())
+ !RetT.isFloating() && !RetT.isBFloat16() && !RetT.isMFloat8())
RetT.makeInteger(RetT.getElementSizeInBits(), false);
// Since the return value must be one type, return a vector type of the
@@ -2378,6 +2405,8 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << "#include <arm_bf16.h>\n";
+ OS << "#include <arm_mfp8.h>\n";
+
OS << "#include <arm_vector_types.h>\n";
// For now, signedness of polynomial types depends on target
@@ -2560,6 +2589,27 @@ void NeonEmitter::runFP16(raw_ostream &OS) {
OS << "#endif /* __ARM_FP16_H */\n";
}
+void NeonEmitter::runMFloat8(raw_ostream &OS) {
+ OS << "/*===---- arm_mfp8 - ARM vector type "
+ "------===\n"
+ " *\n"
+ " *\n"
+ " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
+ "Exceptions.\n"
+ " * See https://llvm.org/LICENSE.txt for license information.\n"
+ " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
+ " *\n"
+ " *===-----------------------------------------------------------------"
+ "------===\n"
+ " */\n\n";
+ OS << "#ifndef __ARM_MFP8_H\n";
+ OS << "#define __ARM_MFP8_H\n\n";
+ OS << "typedef __mfp8 mfloat8_t;\n";
+
+ emitNeonTypeDefs("mQm", OS);
+ OS << "#endif // __ARM_MFP8_H\n";
+}
+
void NeonEmitter::runVectorTypes(raw_ostream &OS) {
OS << "/*===---- arm_vector_types - ARM vector type "
"------===\n"
@@ -2682,6 +2732,10 @@ void clang::EmitBF16(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).runBF16(OS);
}
+void clang::EmitMFloat8(RecordKeeper &Records, raw_ostream &OS) {
+ NeonEmitter(Records).runMFloat8(OS);
+}
+
void clang::EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).runHeader(OS);
}
diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index 42cc704543f18..8eb5b0f35fe6d 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -72,6 +72,7 @@ enum ActionType {
GenArmNeon,
GenArmFP16,
GenArmBF16,
+ GenArmMFloat8,
GenArmVectorType,
GenArmNeonSema,
GenArmNeonTest,
@@ -228,6 +229,7 @@ cl::opt<ActionType> Action(
clEnumValN(GenArmNeon, "gen-arm-neon", "Generate arm_neon.h for clang"),
clEnumValN(GenArmFP16, "gen-arm-fp16", "Generate arm_fp16.h for clang"),
clEnumValN(GenArmBF16, "gen-arm-bf16", "Generate arm_bf16.h for clang"),
+ clEnumValN(GenArmMFloat8, "gen-arm-mfp8", "Generate arm_mfp8.h for clang"),
clEnumValN(GenArmVectorType, "gen-arm-vector-type",
"Generate arm_vector_types.h for clang"),
clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
@@ -463,6 +465,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenArmBF16:
EmitBF16(Records, OS);
break;
+ case GenArmMFloat8:
+ EmitMFloat8(Records, OS);
+ break;
case GenArmNeonSema:
EmitNeonSema(Records, OS);
break;
diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h
index 5f2dd257cb90a..172762e078bf7 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -104,6 +104,7 @@ void EmitClangSyntaxNodeClasses(llvm::RecordKeeper &Records,
void EmitNeon(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitFP16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitBF16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitMFloat8(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitNeonSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitVectorTypes(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitNeonTest(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
>From ceb5124227dc97f8192c4c5928951c0e3911929d Mon Sep 17 00:00:00 2001
From: Caroline Concatto <caroline.concatto at arm.com>
Date: Fri, 2 Aug 2024 08:47:18 +0000
Subject: [PATCH 3/3] [CLANG]Add Scalable vectors for mfloat8_t
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 | 1 +
clang/include/clang/Basic/arm_sve_sme_incl.td | 1 +
.../include/clang/Serialization/ASTBitCodes.h | 2 +-
clang/lib/AST/ASTContext.cpp | 1 +
clang/lib/CodeGen/CodeGenTypes.cpp | 3 +-
clang/test/CodeGen/arm-mfp8.c | 24 ++++++++-
clang/test/Sema/arm-fpm8.cpp | 53 -------------------
clang/test/Sema/arm-mfp8.cpp | 13 ++++-
clang/utils/TableGen/SveEmitter.cpp | 34 ++++++++++--
9 files changed, 68 insertions(+), 64 deletions(-)
delete mode 100644 clang/test/Sema/arm-fpm8.cpp
diff --git a/clang/include/clang/Basic/AArch64SVEACLETypes.def b/clang/include/clang/Basic/AArch64SVEACLETypes.def
index fa9c1ac0491c4..9169af4d3865f 100644
--- a/clang/include/clang/Basic/AArch64SVEACLETypes.def
+++ b/clang/include/clang/Basic/AArch64SVEACLETypes.def
@@ -72,6 +72,7 @@ SVE_VECTOR_TYPE("__SVFloat32_t", "__SVFloat32_t", SveFloat32, SveFloat32Ty, 4, 3
SVE_VECTOR_TYPE("__SVFloat64_t", "__SVFloat64_t", SveFloat64, SveFloat64Ty, 2, 64, true, true, false)
SVE_VECTOR_TYPE("__SVBfloat16_t", "__SVBfloat16_t", SveBFloat16, SveBFloat16Ty, 8, 16, true, false, true)
+SVE_VECTOR_TYPE("__SVMfloat8_t", "__SVMfloat8_t", SveMFloat8, SveMFloat8Ty, 16, 8, false, false, 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 37e3925509836..a330aa9826943 100644
--- a/clang/include/clang/Basic/arm_sve_sme_incl.td
+++ b/clang/include/clang/Basic/arm_sve_sme_incl.td
@@ -160,6 +160,7 @@ def EltTyBool16 : EltType<10>;
def EltTyBool32 : EltType<11>;
def EltTyBool64 : EltType<12>;
def EltTyBFloat16 : EltType<13>;
+def EltTyMFloat8 : EltType<14>;
class MemEltType<int val> {
int Value = val;
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 333aa174567fc..a032095be4af9 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1112,7 +1112,7 @@ enum PredefinedTypeIDs {
///
/// Type IDs for non-predefined types will start at
/// NUM_PREDEF_TYPE_IDs.
-const unsigned NUM_PREDEF_TYPE_IDS = 504;
+const unsigned NUM_PREDEF_TYPE_IDS = 505;
// Ensure we do not overrun the predefined types we reserved
// in the enum PredefinedTypeIDs above.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 6cf7b21115a5b..f2d19db1b1228 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3911,6 +3911,7 @@ ASTContext::getBuiltinVectorTypeInfo(const BuiltinType *Ty) const {
llvm_unreachable("Unsupported builtin vector type");
case BuiltinType::SveInt8:
return SVE_INT_ELTTY(8, 16, true, 1);
+ case BuiltinType::SveMFloat8:
case BuiltinType::SveUint8:
return SVE_INT_ELTTY(8, 16, false, 1);
case BuiltinType::SveInt8x2:
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index c6db0a62e56ba..9922fd8f8eb22 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -495,7 +495,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case BuiltinType::SveBFloat16:
case BuiltinType::SveBFloat16x2:
case BuiltinType::SveBFloat16x3:
- case BuiltinType::SveBFloat16x4: {
+ case BuiltinType::SveBFloat16x4:
+ case BuiltinType::SveMFloat8: {
ASTContext::BuiltinVectorTypeInfo Info =
Context.getBuiltinVectorTypeInfo(cast<BuiltinType>(Ty));
return llvm::ScalableVectorType::get(ConvertType(Info.ElementType),
diff --git a/clang/test/CodeGen/arm-mfp8.c b/clang/test/CodeGen/arm-mfp8.c
index 48201608d2b2b..317aa5cf3818f 100644
--- a/clang/test/CodeGen/arm-mfp8.c
+++ b/clang/test/CodeGen/arm-mfp8.c
@@ -1,6 +1,6 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
-// RUN: %clang_cc1 -emit-llvm -triple aarch64-arm-none-eabi -target-feature -fp8 -target-feature +neon -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-C
-// RUN: %clang_cc1 -emit-llvm -triple aarch64-arm-none-eabi -target-feature -fp8 -target-feature +neon -o - -x c++ %s | FileCheck %s --check-prefixes=CHECK,CHECK-CXX
+// RUN: %clang_cc1 -emit-llvm -triple aarch64-arm-none-eabi -target-feature -fp8 -target-feature +neon -target-feature +sve -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-C
+// RUN: %clang_cc1 -emit-llvm -triple aarch64-arm-none-eabi -target-feature -fp8 -target-feature +neon -target-feature +sve -o - -x c++ %s | FileCheck %s --check-prefixes=CHECK,CHECK-CXX
// REQUIRES: aarch64-registered-target
@@ -79,5 +79,25 @@ mfloat8x8_t test_ret_mfloat8x8_t(mfloat8x8_t v) {
return v;
}
+#include <arm_sve.h>
+// CHECK-C-LABEL: define dso_local <vscale x 16 x i8> @test_ret_svmfloat8_t(
+// CHECK-C-SAME: <vscale x 16 x i8> [[V:%.*]]) #[[ATTR0]] {
+// CHECK-C-NEXT: [[ENTRY:.*:]]
+// CHECK-C-NEXT: [[V_ADDR:%.*]] = alloca <vscale x 16 x i8>, align 16
+// CHECK-C-NEXT: store <vscale x 16 x i8> [[V]], ptr [[V_ADDR]], align 16
+// CHECK-C-NEXT: [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[V_ADDR]], align 16
+// CHECK-C-NEXT: ret <vscale x 16 x i8> [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local <vscale x 16 x i8> @_Z20test_ret_svmfloat8_tu13__SVMfloat8_t(
+// CHECK-CXX-SAME: <vscale x 16 x i8> [[V:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[V_ADDR:%.*]] = alloca <vscale x 16 x i8>, align 16
+// CHECK-CXX-NEXT: store <vscale x 16 x i8> [[V]], ptr [[V_ADDR]], align 16
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[V_ADDR]], align 16
+// CHECK-CXX-NEXT: ret <vscale x 16 x i8> [[TMP0]]
+//
+svmfloat8_t test_ret_svmfloat8_t(svmfloat8_t v) {
+ return v;
+}
//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
// CHECK: {{.*}}
diff --git a/clang/test/Sema/arm-fpm8.cpp b/clang/test/Sema/arm-fpm8.cpp
deleted file mode 100644
index 63eff13f1e290..0000000000000
--- a/clang/test/Sema/arm-fpm8.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=scalar,neon -triple aarch64-arm-none-eabi \
-// RUN: -target-feature -fp8 -target-feature +neon %s
-
-// REQUIRES: aarch64-registered-target
-__fpm8 test_static_cast_from_char(char in) {
- return static_cast<__fpm8>(in); // scalar-error {{static_cast from 'char' to '__fpm8' is not allowed}}
-}
-
-char test_static_cast_to_char(__fpm8 in) {
- return static_cast<char>(in); // scalar-error {{static_cast from '__fpm8' to 'char' is not allowed}}
-}
-void test(bool b) {
- __fpm8 fpm8;
-
- fpm8 + fpm8; // scalar-error {{invalid operands to binary expression ('__fpm8' and '__fpm8')}}
- fpm8 - fpm8; // scalar-error {{invalid operands to binary expression ('__fpm8' and '__fpm8')}}
- fpm8 * fpm8; // scalar-error {{invalid operands to binary expression ('__fpm8' and '__fpm8')}}
- fpm8 / fpm8; // scalar-error {{invalid operands to binary expression ('__fpm8' and '__fpm8')}}
- ++fpm8; // scalar-error {{cannot increment value of type '__fpm8'}}
- --fpm8; // scalar-error {{cannot decrement value of type '__fpm8'}}
-
- char u8;
-
- fpm8 + u8; // scalar-error {{invalid operands to binary expression ('__fpm8' and 'char')}}
- u8 + fpm8; // scalar-error {{invalid operands to binary expression ('char' and '__fpm8')}}
- fpm8 - u8; // scalar-error {{invalid operands to binary expression ('__fpm8' and 'char')}}
- u8 - fpm8; // scalar-error {{invalid operands to binary expression ('char' and '__fpm8')}}
- fpm8 * u8; // scalar-error {{invalid operands to binary expression ('__fpm8' and 'char')}}
- u8 * fpm8; // scalar-error {{invalid operands to binary expression ('char' and '__fpm8')}}
- fpm8 / u8; // scalar-error {{invalid operands to binary expression ('__fpm8' and 'char')}}
- u8 / fpm8; // scalar-error {{invalid operands to binary expression ('char' and '__fpm8')}}
- fpm8 = u8; // scalar-error {{assigning to '__fpm8' from incompatible type 'char'}}
- u8 = fpm8; // scalar-error {{assigning to 'char' from incompatible type '__fpm8'}}
- fpm8 + (b ? u8 : fpm8); // scalar-error {{incompatible operand types ('char' and '__fpm8')}}
-}
-
-#include <arm_neon.h>
-
-void test_vector(fpm8x8_t a, fpm8x8_t b, uint8x8_t c) {
- a + b; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'fpm8x8_t')}}
- a - b; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'fpm8x8_t')}}
- a * b; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'fpm8x8_t')}}
- a / b; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'fpm8x8_t')}}
-
- a + c; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
- a - c; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
- a * c; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
- a / c; // neon-error {{invalid operands to binary expression ('fpm8x8_t' (vector of 8 'fpm8_t' values) and 'uint8x8_t' (vector of 8 'uint8_t' values))}}
- c + b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'fpm8x8_t' (vector of 8 'fpm8_t' values))}}
- c - b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'fpm8x8_t' (vector of 8 'fpm8_t' values))}}
- c * b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'fpm8x8_t' (vector of 8 'fpm8_t' values))}}
- c / b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'fpm8x8_t' (vector of 8 'fpm8_t' values))}}
-}
diff --git a/clang/test/Sema/arm-mfp8.cpp b/clang/test/Sema/arm-mfp8.cpp
index 7a697f7b35274..c8bcf7606338d 100644
--- a/clang/test/Sema/arm-mfp8.cpp
+++ b/clang/test/Sema/arm-mfp8.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=scalar,neon -triple aarch64-arm-none-eabi \
-// RUN: -target-feature -fp8 -target-feature +neon %s
+// RUN: %clang_cc1 -fsyntax-only -verify=scalar,neon,sve -triple aarch64-arm-none-eabi \
+// RUN: -target-feature -fp8 -target-feature +neon -target-feature +sve %s
// REQUIRES: aarch64-registered-target
__mfp8 test_static_cast_from_char(char in) {
@@ -51,3 +51,12 @@ void test_vector(mfloat8x8_t a, mfloat8x8_t b, uint8x8_t c) {
c * b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x8_t' (vector of 8 'mfloat8_t' values))}}
c / b; // neon-error {{invalid operands to binary expression ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x8_t' (vector of 8 'mfloat8_t' values))}}
}
+
+#include <arm_sve.h>
+void test_vector_sve(svmfloat8_t a, svuint8_t c) {
+ a + c; // sve-error {{cannot convert between vector and non-scalar values ('svmfloat8_t' (aka '__SVMfloat8_t') and 'svuint8_t' (aka '__SVUint8_t'))}}
+ a - c; // sve-error {{cannot convert between vector and non-scalar values ('svmfloat8_t' (aka '__SVMfloat8_t') and 'svuint8_t' (aka '__SVUint8_t'))}}
+ a * c; // sve-error {{cannot convert between vector and non-scalar values ('svmfloat8_t' (aka '__SVMfloat8_t') and 'svuint8_t' (aka '__SVUint8_t'))}}
+ a / c; // sve-error {{cannot convert between vector and non-scalar values ('svmfloat8_t' (aka '__SVMfloat8_t') and 'svuint8_t' (aka '__SVUint8_t'))}}
+}
+
diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp
index 7d25914c73539..23ccff17e5e4f 100644
--- a/clang/utils/TableGen/SveEmitter.cpp
+++ b/clang/utils/TableGen/SveEmitter.cpp
@@ -67,7 +67,7 @@ class ImmCheck {
};
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;
@@ -77,10 +77,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);
@@ -103,6 +103,10 @@ class SVEType {
bool isDefault() const { return DefaultType; }
bool isFloat() const { return Float && !BFloat; }
bool isBFloat() const { return BFloat && !Float; }
+ bool isMFloat() const {
+ return MFloat && !BFloat && !Float;
+ ;
+ }
bool isFloatingPoint() const { return Float || BFloat; }
bool isInteger() const {
return !isFloatingPoint() && !Predicate && !Svcount;
@@ -447,6 +451,8 @@ std::string SVEType::builtin_str() const {
else if (isBFloat()) {
assert(ElementBitwidth == 16 && "Not a valid BFloat.");
S += "y";
+ } else if (isMFloat()) {
+ S += "m";
}
if (!isFloatingPoint()) {
@@ -502,6 +508,8 @@ std::string SVEType::str() const {
S += "bool";
else if (isBFloat())
S += "bfloat";
+ else if (isMFloat())
+ S += "mfloat";
else
S += "int";
@@ -567,6 +575,12 @@ void SVEType::applyTypespec(StringRef TS) {
Float = false;
ElementBitwidth = 16;
break;
+ case 'm':
+ MFloat = true;
+ Float = false;
+ BFloat = false;
+ ElementBitwidth = 8;
+ break;
default:
llvm_unreachable("Unhandled type code!");
}
@@ -1018,6 +1032,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()));
@@ -1111,6 +1127,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:
@@ -1288,6 +1309,9 @@ void SVEEmitter::createHeader(raw_ostream &OS) {
OS << "#include <arm_bf16.h>\n";
OS << "#include <arm_vector_types.h>\n";
+ OS << "typedef __SVMfloat8_t svmfloat8_t;\n\n";
+ OS << "#include <arm_mfp8.h>\n";
+
OS << "typedef __SVFloat32_t svfloat32_t;\n";
OS << "typedef __SVFloat64_t svfloat64_t;\n";
OS << "typedef __clang_svint8x2_t svint8x2_t;\n";
More information about the cfe-commits
mailing list