stuij updated this revision to Diff 261851. stuij added a comment. I've amended this patch to conform to the general Bfloat -> BFloat convention changes requested in the dependent BFloat IR patch (D78190 <https://reviews.llvm.org/D78190>).
I also folded in two other downstream patches, which allow for the ?: operator on bf16 values and prohibit conversions between integer and __bf16. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D76077/new/ https://reviews.llvm.org/D76077 Files: clang/docs/LanguageExtensions.rst clang/include/clang-c/Index.h clang/include/clang/AST/ASTContext.h clang/include/clang/AST/BuiltinTypes.def clang/include/clang/AST/Type.h clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Basic/Specifiers.h clang/include/clang/Basic/TargetBuiltins.h clang/include/clang/Basic/TargetInfo.h clang/include/clang/Basic/TokenKinds.def clang/include/clang/Sema/DeclSpec.h clang/include/clang/Serialization/ASTBitCodes.h clang/lib/AST/ASTContext.cpp clang/lib/AST/ItaniumMangle.cpp clang/lib/AST/MicrosoftMangle.cpp clang/lib/AST/NSAPI.cpp clang/lib/AST/PrintfFormatString.cpp clang/lib/AST/Type.cpp clang/lib/AST/TypeLoc.cpp clang/lib/Basic/TargetInfo.cpp clang/lib/Basic/Targets/AArch64.cpp clang/lib/Basic/Targets/AArch64.h clang/lib/Basic/Targets/ARM.cpp clang/lib/Basic/Targets/ARM.h clang/lib/CodeGen/CGBuiltin.cpp clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenTypeCache.h clang/lib/CodeGen/CodeGenTypes.cpp clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/CodeGen/TargetInfo.cpp clang/lib/Format/FormatToken.cpp clang/lib/Index/USRGeneration.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/ParseExpr.cpp clang/lib/Parse/ParseExprCXX.cpp clang/lib/Parse/ParseTentative.cpp clang/lib/Sema/DeclSpec.cpp clang/lib/Sema/SemaCast.cpp clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaOverload.cpp clang/lib/Sema/SemaTemplateVariadic.cpp clang/lib/Sema/SemaType.cpp clang/lib/Serialization/ASTCommon.cpp clang/lib/Serialization/ASTReader.cpp clang/test/CodeGen/arm-mangle-16bit-float.cpp clang/test/Sema/arm-bf16-forbidden-ops.c clang/test/Sema/arm-bf16-forbidden-ops.cpp clang/test/Sema/arm-bfloat.cpp clang/tools/libclang/CXType.cpp
Index: clang/tools/libclang/CXType.cpp =================================================================== --- clang/tools/libclang/CXType.cpp +++ clang/tools/libclang/CXType.cpp @@ -608,6 +608,7 @@ TKIND(Elaborated); TKIND(Pipe); TKIND(Attributed); + TKIND(BFloat16); #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) TKIND(Id); #include "clang/Basic/OpenCLImageTypes.def" #undef IMAGE_TYPE Index: clang/test/Sema/arm-bfloat.cpp =================================================================== --- /dev/null +++ clang/test/Sema/arm-bfloat.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 \ +// RUN: -triple aarch64-arm-none-eabi -target-cpu cortex-a75 \ +// RUN: -target-feature +bf16 -target-feature +neon %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 \ +// RUN: -triple arm-arm-none-eabi -target-cpu cortex-a53 \ +// RUN: -target-feature +bf16 -target-feature +neon %s + +void test(bool b) { + __bf16 bf16; + + bf16 + bf16; // expected-error {{invalid operands to binary expression ('__bf16' and '__bf16')}} + bf16 - bf16; // expected-error {{invalid operands to binary expression ('__bf16' and '__bf16')}} + bf16 * bf16; // expected-error {{invalid operands to binary expression ('__bf16' and '__bf16')}} + bf16 / bf16; // expected-error {{invalid operands to binary expression ('__bf16' and '__bf16')}} + + __fp16 fp16; + + bf16 + fp16; // expected-error {{invalid operands to binary expression ('__bf16' and '__fp16')}} + fp16 + bf16; // expected-error {{invalid operands to binary expression ('__fp16' and '__bf16')}} + bf16 - fp16; // expected-error {{invalid operands to binary expression ('__bf16' and '__fp16')}} + fp16 - bf16; // expected-error {{invalid operands to binary expression ('__fp16' and '__bf16')}} + bf16 * fp16; // expected-error {{invalid operands to binary expression ('__bf16' and '__fp16')}} + fp16 * bf16; // expected-error {{invalid operands to binary expression ('__fp16' and '__bf16')}} + bf16 / fp16; // expected-error {{invalid operands to binary expression ('__bf16' and '__fp16')}} + fp16 / bf16; // expected-error {{invalid operands to binary expression ('__fp16' and '__bf16')}} + bf16 = fp16; // expected-error {{assigning to '__bf16' from incompatible type '__fp16'}} + fp16 = bf16; // expected-error {{assigning to '__fp16' from incompatible type '__bf16'}} + bf16 + (b ? fp16 : bf16); // expected-error {{incompatible operand types ('__fp16' and '__bf16')}} +} Index: clang/test/Sema/arm-bf16-forbidden-ops.cpp =================================================================== --- /dev/null +++ clang/test/Sema/arm-bf16-forbidden-ops.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64 -target-feature +bf16 %s + +__bf16 test_static_cast_from_float(float in) { + return static_cast<__bf16>(in); // expected-error {{static_cast from 'float' to '__bf16' is not allowed}} +} + +__bf16 test_static_cast_from_float_literal(void) { + return static_cast<__bf16>(1.0f); // expected-error {{static_cast from 'float' to '__bf16' is not allowed}} +} + +__bf16 test_static_cast_from_int(int in) { + return static_cast<__bf16>(in); // expected-error {{static_cast from 'int' to '__bf16' is not allowed}} +} + +__bf16 test_static_cast_from_int_literal(void) { + return static_cast<__bf16>(1); // expected-error {{static_cast from 'int' to '__bf16' is not allowed}} +} + +__bf16 test_static_cast_bfloat(__bf16 in) { + return static_cast<__bf16>(in); // this one should work +} + +float test_static_cast_to_float(__bf16 in) { + return static_cast<float>(in); // expected-error {{static_cast from '__bf16' to 'float' is not allowed}} +} + +int test_static_cast_to_int(__bf16 in) { + return static_cast<int>(in); // expected-error {{static_cast from '__bf16' to 'int' is not allowed}} +} + +__bf16 test_implicit_from_float(float in) { + return in; // expected-error {{cannot initialize return object of type '__bf16' with an lvalue of type 'float'}} +} + +__bf16 test_implicit_from_float_literal() { + return 1.0f; // expected-error {{cannot initialize return object of type '__bf16' with an rvalue of type 'float'}} +} + +__bf16 test_implicit_from_int(int in) { + return in; // expected-error {{cannot initialize return object of type '__bf16' with an lvalue of type 'int'}} +} + +__bf16 test_implicit_from_int_literal() { + return 1; // expected-error {{cannot initialize return object of type '__bf16' with an rvalue of type 'int'}} +} + +__bf16 test_implicit_bfloat(__bf16 in) { + return in; // this one should work +} + +float test_implicit_to_float(__bf16 in) { + return in; // expected-error {{cannot initialize return object of type 'float' with an lvalue of type '__bf16'}} +} + +int test_implicit_to_int(__bf16 in) { + return in; // expected-error {{cannot initialize return object of type 'int' with an lvalue of type '__bf16'}} +} + +__bf16 test_cond(__bf16 a, __bf16 b, bool which) { + // Conditional operator _should_ be supported, without nonsense + // complaints like 'types __bf16 and __bf16 are not compatible' + return which ? a : b; +} + +__bf16 test_cond_float(__bf16 a, __bf16 b, bool which) { + return which ? a : 1.0f; // expected-error {{incompatible operand types ('__bf16' and 'float')}} +} + +__bf16 test_cond_int(__bf16 a, __bf16 b, bool which) { + return which ? a : 1; // expected-error {{incompatible operand types ('__bf16' and 'int')}} +} Index: clang/test/Sema/arm-bf16-forbidden-ops.c =================================================================== --- /dev/null +++ clang/test/Sema/arm-bf16-forbidden-ops.c @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64 -target-feature +bf16 %s + +__bf16 test_cast_from_float(float in) { + return (__bf16)in; // expected-error {{cannot type-cast to __bf16}} +} + +__bf16 test_cast_from_float_literal(void) { + return (__bf16)1.0f; // expected-error {{cannot type-cast to __bf16}} +} + +__bf16 test_cast_from_int(int in) { + return (__bf16)in; // expected-error {{cannot type-cast to __bf16}} +} + +__bf16 test_cast_from_int_literal(void) { + return (__bf16)1; // expected-error {{cannot type-cast to __bf16}} +} + +__bf16 test_cast_bfloat(__bf16 in) { + return (__bf16)in; // this one should work +} + +float test_cast_to_float(__bf16 in) { + return (float)in; // expected-error {{cannot type-cast from __bf16}} +} + +int test_cast_to_int(__bf16 in) { + return (int)in; // expected-error {{cannot type-cast from __bf16}} +} + +__bf16 test_implicit_from_float(float in) { + return in; // expected-error {{returning 'float' from a function with incompatible result type '__bf16'}} +} + +__bf16 test_implicit_from_float_literal(void) { + return 1.0f; // expected-error {{returning 'float' from a function with incompatible result type '__bf16'}} +} + +__bf16 test_implicit_from_int(int in) { + return in; // expected-error {{returning 'int' from a function with incompatible result type '__bf16'}} +} + +__bf16 test_implicit_from_int_literal(void) { + return 1; // expected-error {{returning 'int' from a function with incompatible result type '__bf16'}} +} + +__bf16 test_implicit_bfloat(__bf16 in) { + return in; // this one should work +} + +float test_implicit_to_float(__bf16 in) { + return in; // expected-error {{returning '__bf16' from a function with incompatible result type 'float'}} +} + +int test_implicit_to_int(__bf16 in) { + return in; // expected-error {{returning '__bf16' from a function with incompatible result type 'int'}} +} + +__bf16 test_cond(__bf16 a, __bf16 b, _Bool which) { + // Conditional operator _should_ be supported, without nonsense + // complaints like 'types __bf16 and __bf16 are not compatible' + return which ? a : b; +} + +__bf16 test_cond_float(__bf16 a, __bf16 b, _Bool which) { + return which ? a : 1.0f; // expected-error {{incompatible operand types ('__bf16' and 'float')}} +} + +__bf16 test_cond_int(__bf16 a, __bf16 b, _Bool which) { + return which ? a : 1; // expected-error {{incompatible operand types ('__bf16' and 'int')}} +} Index: clang/test/CodeGen/arm-mangle-16bit-float.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/arm-mangle-16bit-float.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple aarch64-arm-none-eabi -fallow-half-arguments-and-returns -target-feature +bf16 -target-feature +fullfp16 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK64 +// RUN: %clang_cc1 -triple arm-arm-none-eabi -fallow-half-arguments-and-returns -target-feature +bf16 -target-feature +fullfp16 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK32 + +// CHECK64: define {{.*}}void @_Z3foou6__bf16(bfloat %b) +// CHECK32: define {{.*}}void @_Z3foou6__bf16(i32 %b.coerce) +void foo(__bf16 b) {} + +// CHECK64: define {{.*}}void @_Z3barDh(half %b) +// CHECK32: define {{.*}}void @_Z3barDh(i32 %b.coerce) +void bar(__fp16 b) {} Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -6829,6 +6829,9 @@ case PREDEF_TYPE_INT128_ID: T = Context.Int128Ty; break; + case PREDEF_TYPE_BFLOAT16_ID: + T = Context.BFloat16Ty; + break; case PREDEF_TYPE_HALF_ID: T = Context.HalfTy; break; Index: clang/lib/Serialization/ASTCommon.cpp =================================================================== --- clang/lib/Serialization/ASTCommon.cpp +++ clang/lib/Serialization/ASTCommon.cpp @@ -249,6 +249,9 @@ case BuiltinType::OMPIterator: ID = PREDEF_TYPE_OMP_ITERATOR; break; + case BuiltinType::BFloat16: + ID = PREDEF_TYPE_BFLOAT16_ID; + break; } return TypeIdx(ID); Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -1521,6 +1521,12 @@ Result = Context.Float16Ty; break; case DeclSpec::TST_half: Result = Context.HalfTy; break; + case DeclSpec::TST_BFloat16: + if (!S.Context.getTargetInfo().hasBFloat16Type()) + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__bf16"; + Result = Context.BFloat16Ty; + break; case DeclSpec::TST_float: Result = Context.FloatTy; break; case DeclSpec::TST_double: if (DS.getTypeSpecWidth() == DeclSpec::TSW_long) @@ -7575,7 +7581,8 @@ BTy->getKind() == BuiltinType::LongLong || BTy->getKind() == BuiltinType::ULongLong || BTy->getKind() == BuiltinType::Float || - BTy->getKind() == BuiltinType::Half; + BTy->getKind() == BuiltinType::Half || + BTy->getKind() == BuiltinType::BFloat16; } /// HandleNeonVectorTypeAttr - The "neon_vector_type" and Index: clang/lib/Sema/SemaTemplateVariadic.cpp =================================================================== --- clang/lib/Sema/SemaTemplateVariadic.cpp +++ clang/lib/Sema/SemaTemplateVariadic.cpp @@ -881,6 +881,7 @@ case TST_auto: case TST_auto_type: case TST_decltype_auto: + case TST_BFloat16: #define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" case TST_unknown_anytype: Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -1870,6 +1870,8 @@ // FIXME: disable conversions between long double and __float128 if // their representation is different until there is back end support // We of course allow this conversion if long double is really double. + if (FromType == S.Context.BFloat16Ty || ToType == S.Context.BFloat16Ty) + return false; if (&S.Context.getFloatTypeSemantics(FromType) != &S.Context.getFloatTypeSemantics(ToType)) { bool Float128AndLongDouble = ((FromType == S.Context.Float128Ty && @@ -1888,6 +1890,10 @@ ToType->isIntegralType(S.Context)) || (FromType->isIntegralOrUnscopedEnumerationType() && ToType->isRealFloatingType())) { + // SDCOMP-54723: conversions between int and bfloat are not permitted + if (FromType->isBFloat16Type() || ToType->isBFloat16Type()) + return false; + // Floating-integral conversions (C++ 4.9). SCS.Second = ICK_Floating_Integral; FromType = ToType.getUnqualifiedType(); Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -7991,6 +7991,11 @@ return ResTy; } + // And if they're both bfloat (which isn't arithmetic), that's fine too. + if (LHSTy->isBFloat16Type() && RHSTy->isBFloat16Type()) { + return LHSTy; + } + // If both operands are the same structure or union type, the result is that // type. if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) { // C99 6.5.15p3 Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -138,6 +138,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___bf16: case tok::kw__Float16: case tok::kw___float128: case tok::kw_wchar_t: Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -1959,6 +1959,9 @@ case NeonTypeFlags::Float64: assert(!shift && "cannot shift float types!"); return (1 << IsQuad) - 1; + case NeonTypeFlags::BFloat16: + assert(!shift && "cannot shift float types!"); + return (4 << IsQuad) - 1; } llvm_unreachable("Invalid NeonTypeFlag!"); } @@ -1998,6 +2001,8 @@ return Context.FloatTy; case NeonTypeFlags::Float64: return Context.DoubleTy; + case NeonTypeFlags::BFloat16: + return Context.BFloat16Ty; } llvm_unreachable("Invalid NeonTypeFlag!"); } Index: clang/lib/Sema/SemaCast.cpp =================================================================== --- clang/lib/Sema/SemaCast.cpp +++ clang/lib/Sema/SemaCast.cpp @@ -2754,6 +2754,20 @@ return; } + // Can't cast to or from bfloat + if (DestType->isBFloat16Type() && !SrcType->isBFloat16Type()) { + Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_cast_to_bfloat) + << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + if (SrcType->isBFloat16Type() && !DestType->isBFloat16Type()) { + Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_cast_from_bfloat) + << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + // If either type is a pointer, the other type has to be either an // integer or a pointer. if (!DestType->isArithmeticType()) { Index: clang/lib/Sema/DeclSpec.cpp =================================================================== --- clang/lib/Sema/DeclSpec.cpp +++ clang/lib/Sema/DeclSpec.cpp @@ -368,6 +368,7 @@ case TST_unspecified: case TST_void: case TST_wchar: + case TST_BFloat16: #define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" return false; @@ -566,6 +567,7 @@ case DeclSpec::TST_underlyingType: return "__underlying_type"; case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; case DeclSpec::TST_atomic: return "_Atomic"; + case DeclSpec::TST_BFloat16: return "__bf16"; #define GENERIC_IMAGE_TYPE(ImgType, Id) \ case DeclSpec::TST_##ImgType##_t: \ return #ImgType "_t"; Index: clang/lib/Parse/ParseTentative.cpp =================================================================== --- clang/lib/Parse/ParseTentative.cpp +++ clang/lib/Parse/ParseTentative.cpp @@ -1135,6 +1135,7 @@ case tok::kw_char: case tok::kw_const: case tok::kw_double: + case tok::kw___bf16: case tok::kw__Float16: case tok::kw___float128: case tok::kw_enum: @@ -1725,6 +1726,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___bf16: case tok::kw__Float16: case tok::kw___float128: case tok::kw_void: @@ -1838,6 +1840,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___bf16: case tok::kw__Float16: case tok::kw___float128: case tok::kw_void: Index: clang/lib/Parse/ParseExprCXX.cpp =================================================================== --- clang/lib/Parse/ParseExprCXX.cpp +++ clang/lib/Parse/ParseExprCXX.cpp @@ -2197,6 +2197,9 @@ case tok::kw___int128: DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw___bf16: + DS.SetTypeSpecType(DeclSpec::TST_BFloat16, Loc, PrevSpec, DiagID, Policy); + break; case tok::kw_half: DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID, Policy); break; Index: clang/lib/Parse/ParseExpr.cpp =================================================================== --- clang/lib/Parse/ParseExpr.cpp +++ clang/lib/Parse/ParseExpr.cpp @@ -1498,6 +1498,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___bf16: case tok::kw__Float16: case tok::kw___float128: case tok::kw_void: Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -3842,6 +3842,10 @@ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw___bf16: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_BFloat16, Loc, PrevSpec, + DiagID, Policy); + break; case tok::kw_float: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID, Policy); @@ -4918,6 +4922,7 @@ case tok::kw_char32_t: case tok::kw_int: case tok::kw__ExtInt: + case tok::kw___bf16: case tok::kw_half: case tok::kw_float: case tok::kw_double: @@ -4999,6 +5004,7 @@ case tok::kw_int: case tok::kw__ExtInt: case tok::kw_half: + case tok::kw___bf16: case tok::kw_float: case tok::kw_double: case tok::kw__Accum: @@ -5166,6 +5172,7 @@ case tok::kw_int: case tok::kw__ExtInt: case tok::kw_half: + case tok::kw___bf16: case tok::kw_float: case tok::kw_double: case tok::kw__Accum: Index: clang/lib/Index/USRGeneration.cpp =================================================================== --- clang/lib/Index/USRGeneration.cpp +++ clang/lib/Index/USRGeneration.cpp @@ -753,6 +753,7 @@ case BuiltinType::SatUShortFract: case BuiltinType::SatUFract: case BuiltinType::SatULongFract: + case BuiltinType::BFloat16: IgnoreResults = true; return; case BuiltinType::ObjCId: Index: clang/lib/Format/FormatToken.cpp =================================================================== --- clang/lib/Format/FormatToken.cpp +++ clang/lib/Format/FormatToken.cpp @@ -50,6 +50,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___bf16: case tok::kw__Float16: case tok::kw___float128: case tok::kw_wchar_t: Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -6051,10 +6051,10 @@ if (isIllegalVectorType(Ty)) return coerceIllegalVector(Ty); - // _Float16 and __fp16 get passed as if it were an int or float, but with - // the top 16 bits unspecified. This is not done for OpenCL as it handles the - // half type natively, and does not need to interwork with AAPCS code. - if ((Ty->isFloat16Type() || Ty->isHalfType()) && + // _Float16, __fp16 and __bf16 get passed as if it were an int or float, but + // with the top 16 bits unspecified. This is not done for OpenCL as it handles + // the half type natively, and does not need to interwork with AAPCS code. + if ((Ty->isFloat16Type() || Ty->isHalfType() || Ty->isBFloat16Type()) && !getContext().getLangOpts().NativeHalfArgsAndReturns) { llvm::Type *ResType = IsAAPCS_VFP ? llvm::Type::getFloatTy(getVMContext()) : @@ -6254,6 +6254,7 @@ // FP16 vectors should be converted to integer vectors if (!getTarget().hasLegalHalfType() && (VT->getElementType()->isFloat16Type() || + VT->getElementType()->isBFloat16Type() || VT->getElementType()->isHalfType())) return coerceIllegalVector(RetTy); } @@ -6261,7 +6262,7 @@ // _Float16 and __fp16 get returned as if it were an int or float, but with // the top 16 bits unspecified. This is not done for OpenCL as it handles the // half type natively, and does not need to interwork with AAPCS code. - if ((RetTy->isFloat16Type() || RetTy->isHalfType()) && + if ((RetTy->isFloat16Type() || RetTy->isBFloat16Type() || RetTy->isHalfType()) && !getContext().getLangOpts().NativeHalfArgsAndReturns) { llvm::Type *ResType = IsAAPCS_VFP ? llvm::Type::getFloatTy(getVMContext()) : @@ -6351,11 +6352,13 @@ /// isIllegalVector - check whether Ty is an illegal vector type. bool ARMABIInfo::isIllegalVectorType(QualType Ty) const { if (const VectorType *VT = Ty->getAs<VectorType> ()) { - // On targets that don't support FP16, FP16 is expanded into float, and we - // don't want the ABI to depend on whether or not FP16 is supported in - // hardware. Thus return false to coerce FP16 vectors into integer vectors. + // On targets that don't support half, fp16 or bfloat, they are expanded + // into float, and we don't want the ABI to depend on whether or not they + // are supported in hardware. Thus return false to coerce vectors of these + // types into integer vectors. if (!getTarget().hasLegalHalfType() && (VT->getElementType()->isFloat16Type() || + VT->getElementType()->isBFloat16Type() || VT->getElementType()->isHalfType())) return true; if (isAndroid()) { @@ -6408,6 +6411,7 @@ } else { if (const VectorType *VT = Ty->getAs<VectorType>()) return (VT->getElementType()->isFloat16Type() || + VT->getElementType()->isBFloat16Type() || VT->getElementType()->isHalfType()); return false; } Index: clang/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- clang/lib/CodeGen/ItaniumCXXABI.cpp +++ clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3027,6 +3027,7 @@ case BuiltinType::SatUShortFract: case BuiltinType::SatUFract: case BuiltinType::SatULongFract: + case BuiltinType::BFloat16: return false; case BuiltinType::Dependent: Index: clang/lib/CodeGen/CodeGenTypes.cpp =================================================================== --- clang/lib/CodeGen/CodeGenTypes.cpp +++ clang/lib/CodeGen/CodeGenTypes.cpp @@ -293,6 +293,12 @@ else return llvm::Type::getInt16Ty(VMContext); } + if (&format == &llvm::APFloat::BFloat()) { + if (UseNativeHalf) + return llvm::Type::getBFloatTy(VMContext); + else + return llvm::Type::getInt16Ty(VMContext); + } if (&format == &llvm::APFloat::IEEEsingle()) return llvm::Type::getFloatTy(VMContext); if (&format == &llvm::APFloat::IEEEdouble()) @@ -484,6 +490,7 @@ /* UseNativeHalf = */ true); break; + case BuiltinType::BFloat16: case BuiltinType::Half: // Half FP can either be storage-only (lowered to i16) or native. ResultType = getTypeForFormat( Index: clang/lib/CodeGen/CodeGenTypeCache.h =================================================================== --- clang/lib/CodeGen/CodeGenTypeCache.h +++ clang/lib/CodeGen/CodeGenTypeCache.h @@ -35,8 +35,8 @@ /// i8, i16, i32, and i64 llvm::IntegerType *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty; - /// float, double - llvm::Type *HalfTy, *FloatTy, *DoubleTy; + /// half, bfloat, float, double + llvm::Type *HalfTy, *BFloatTy, *FloatTy, *DoubleTy; /// int llvm::IntegerType *IntTy; Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -112,6 +112,7 @@ Int32Ty = llvm::Type::getInt32Ty(LLVMContext); Int64Ty = llvm::Type::getInt64Ty(LLVMContext); HalfTy = llvm::Type::getHalfTy(LLVMContext); + BFloatTy = llvm::Type::getBFloatTy(LLVMContext); FloatTy = llvm::Type::getFloatTy(LLVMContext); DoubleTy = llvm::Type::getDoubleTy(LLVMContext); PointerWidthInBits = C.getTargetInfo().getPointerWidth(0); Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -761,6 +761,7 @@ case BuiltinType::Float: case BuiltinType::LongDouble: case BuiltinType::Float16: + case BuiltinType::BFloat16: case BuiltinType::Float128: case BuiltinType::Double: // FIXME: For targets where long double and __float128 have the same size, Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -4477,6 +4477,11 @@ case NeonTypeFlags::Int16: case NeonTypeFlags::Poly16: return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad)); + case NeonTypeFlags::BFloat16: + if (HasLegalHalfType) + return llvm::VectorType::get(CGF->BFloatTy, V1Ty ? 1 : (4 << IsQuad)); + else + return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad)); case NeonTypeFlags::Float16: if (HasLegalHalfType) return llvm::VectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad)); Index: clang/lib/Basic/Targets/ARM.h =================================================================== --- clang/lib/Basic/Targets/ARM.h +++ clang/lib/Basic/Targets/ARM.h @@ -182,6 +182,8 @@ int getEHDataRegisterNumber(unsigned RegNo) const override; bool hasSjLjLowering() const override; + + const char *getBFloat16Mangling() const override { return "u6__bf16"; }; }; class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo { Index: clang/lib/Basic/Targets/ARM.cpp =================================================================== --- clang/lib/Basic/Targets/ARM.cpp +++ clang/lib/Basic/Targets/ARM.cpp @@ -25,6 +25,9 @@ IsAAPCS = true; DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; + BFloat16Width = BFloat16Align = 16; + BFloat16Format = &llvm::APFloat::BFloat(); + const llvm::Triple &T = getTriple(); bool IsNetBSD = T.isOSNetBSD(); @@ -74,6 +77,8 @@ DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; else DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32; + BFloat16Width = BFloat16Align = 16; + BFloat16Format = &llvm::APFloat::BFloat(); WCharType = SignedInt; @@ -428,6 +433,7 @@ HasMatMul = 0; HasFloat16 = true; ARMCDECoprocMask = 0; + HasBFloat16 = false; // This does not diagnose illegal cases like having both // "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64". @@ -498,6 +504,8 @@ Feature <= "+cdecp7") { unsigned Coproc = Feature.back() - '0'; ARMCDECoprocMask |= (1U << Coproc); + } else if (Feature == "+bf16") { + HasBFloat16 = true; } } Index: clang/lib/Basic/Targets/AArch64.h =================================================================== --- clang/lib/Basic/Targets/AArch64.h +++ clang/lib/Basic/Targets/AArch64.h @@ -119,6 +119,7 @@ int getEHDataRegisterNumber(unsigned RegNo) const override; + const char *getBFloat16Mangling() const override { return "u6__bf16"; }; bool hasInt128Type() const override; }; Index: clang/lib/Basic/Targets/AArch64.cpp =================================================================== --- clang/lib/Basic/Targets/AArch64.cpp +++ clang/lib/Basic/Targets/AArch64.cpp @@ -70,6 +70,9 @@ LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128; LongDoubleFormat = &llvm::APFloat::IEEEquad(); + BFloat16Width = BFloat16Align = 16; + BFloat16Format = &llvm::APFloat::BFloat(); + // Make __builtin_ms_va_list available. HasBuiltinMSVaList = true; @@ -360,6 +363,7 @@ HasMTE = false; HasTME = false; HasMatMul = false; + HasBFloat16 = false; ArchKind = llvm::AArch64::ArchKind::ARMV8A; for (const auto &Feature : Features) { @@ -397,6 +401,8 @@ HasTME = true; if (Feature == "+i8mm") HasMatMul = true; + if (Feature == "+bf16") + HasBFloat16 = true; } setDataLayout(); Index: clang/lib/Basic/TargetInfo.cpp =================================================================== --- clang/lib/Basic/TargetInfo.cpp +++ clang/lib/Basic/TargetInfo.cpp @@ -36,6 +36,7 @@ HasLegalHalfType = false; HasFloat128 = false; HasFloat16 = false; + HasBFloat16 = false; PointerWidth = PointerAlign = 32; BoolWidth = BoolAlign = 8; IntWidth = IntAlign = 32; Index: clang/lib/AST/TypeLoc.cpp =================================================================== --- clang/lib/AST/TypeLoc.cpp +++ clang/lib/AST/TypeLoc.cpp @@ -375,6 +375,7 @@ case BuiltinType::SatUShortFract: case BuiltinType::SatUFract: case BuiltinType::SatULongFract: + case BuiltinType::BFloat16: llvm_unreachable("Builtin type needs extra local data!"); // Fall through, if the impossible happens. Index: clang/lib/AST/Type.cpp =================================================================== --- clang/lib/AST/Type.cpp +++ clang/lib/AST/Type.cpp @@ -2071,7 +2071,8 @@ bool Type::isArithmeticType() const { if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Float128; + BT->getKind() <= BuiltinType::Float128 && + BT->getKind() != BuiltinType::BFloat16; if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2). // If a body isn't seen by the time we get here, return false. @@ -2856,6 +2857,8 @@ return "unsigned __int128"; case Half: return Policy.Half ? "half" : "__fp16"; + case BFloat16: + return "__bf16"; case Float: return "float"; case Double: Index: clang/lib/AST/PrintfFormatString.cpp =================================================================== --- clang/lib/AST/PrintfFormatString.cpp +++ clang/lib/AST/PrintfFormatString.cpp @@ -752,6 +752,7 @@ case BuiltinType::UInt128: case BuiltinType::Int128: case BuiltinType::Half: + case BuiltinType::BFloat16: case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::ShortAccum: Index: clang/lib/AST/NSAPI.cpp =================================================================== --- clang/lib/AST/NSAPI.cpp +++ clang/lib/AST/NSAPI.cpp @@ -485,6 +485,7 @@ case BuiltinType::OMPArraySection: case BuiltinType::OMPArrayShaping: case BuiltinType::OMPIterator: + case BuiltinType::BFloat16: break; } Index: clang/lib/AST/MicrosoftMangle.cpp =================================================================== --- clang/lib/AST/MicrosoftMangle.cpp +++ clang/lib/AST/MicrosoftMangle.cpp @@ -2114,6 +2114,7 @@ case BuiltinType::SatUShortFract: case BuiltinType::SatUFract: case BuiltinType::SatULongFract: + case BuiltinType::BFloat16: case BuiltinType::Float128: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID( Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -2762,6 +2762,11 @@ Out << TI->getFloat128Mangling(); break; } + case BuiltinType::BFloat16: { + const TargetInfo *TI = &getASTContext().getTargetInfo(); + Out << TI->getBFloat16Mangling(); + break; + } case BuiltinType::NullPtr: Out << "Dn"; break; @@ -3178,6 +3183,7 @@ case BuiltinType::Double: EltName = "float64_t"; break; case BuiltinType::Float: EltName = "float32_t"; break; case BuiltinType::Half: EltName = "float16_t";break; + case BuiltinType::BFloat16: EltName = "bfloat16x1_t";break; default: llvm_unreachable("unexpected Neon vector element type"); } @@ -3229,6 +3235,8 @@ return "Float32"; case BuiltinType::Double: return "Float64"; + case BuiltinType::BFloat16: + return "BFloat16"; default: llvm_unreachable("Unexpected vector element base type"); } Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -100,7 +100,7 @@ using namespace clang; enum FloatingRank { - Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank + BFloat16Rank, Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank }; /// \returns location that is relevant when searching for Doc comments related @@ -1446,6 +1446,8 @@ // half type (OpenCL 6.1.1.1) / ARM NEON __fp16 InitBuiltinType(HalfTy, BuiltinType::Half); + InitBuiltinType(BFloat16Ty, BuiltinType::BFloat16); + // Builtin type used to help define __builtin_va_list. VaListTagDecl = nullptr; @@ -1649,6 +1651,8 @@ switch (T->castAs<BuiltinType>()->getKind()) { default: llvm_unreachable("Not a floating point type!"); + case BuiltinType::BFloat16: + return Target->getBFloat16Format(); case BuiltinType::Float16: case BuiltinType::Half: return Target->getHalfFormat(); @@ -2032,6 +2036,9 @@ Width = Target->getLongFractWidth(); Align = Target->getLongFractAlign(); break; + case BuiltinType::BFloat16: + Width = Target->getBFloat16Width(); + Align = Target->getBFloat16Align(); case BuiltinType::Float16: case BuiltinType::Half: if (Target->hasFloat16Type() || !getLangOpts().OpenMP || @@ -5897,6 +5904,7 @@ case BuiltinType::Double: return DoubleRank; case BuiltinType::LongDouble: return LongDoubleRank; case BuiltinType::Float128: return Float128Rank; + case BuiltinType::BFloat16: return BFloat16Rank; } } @@ -5909,6 +5917,7 @@ FloatingRank EltRank = getFloatingRank(Size); if (Domain->isComplexType()) { switch (EltRank) { + case BFloat16Rank: case Float16Rank: case HalfRank: llvm_unreachable("Complex half is not supported"); case FloatRank: return FloatComplexTy; @@ -5921,6 +5930,7 @@ assert(Domain->isRealFloatingType() && "Unknown domain!"); switch (EltRank) { case Float16Rank: return HalfTy; + case BFloat16Rank: return BFloat16Ty; case HalfRank: return HalfTy; case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; @@ -6898,6 +6908,7 @@ case BuiltinType::LongDouble: return 'D'; case BuiltinType::NullPtr: return '*'; // like char* + case BuiltinType::BFloat16: case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::Half: @@ -9777,6 +9788,11 @@ // Read the base type. switch (*Str++) { default: llvm_unreachable("Unknown builtin type letter!"); + case 'y': + assert(HowLong == 0 && !Signed && !Unsigned && + "Bad modifiers used with 'y'!"); + Type = Context.BFloat16Ty; + break; case 'v': assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers used with 'v'!"); Index: clang/include/clang/Serialization/ASTBitCodes.h =================================================================== --- clang/include/clang/Serialization/ASTBitCodes.h +++ clang/include/clang/Serialization/ASTBitCodes.h @@ -1057,6 +1057,9 @@ /// The placeholder type for OpenMP iterator expression. PREDEF_TYPE_OMP_ITERATOR = 71, + /// \brief The '__bf16' type + PREDEF_TYPE_BFLOAT16_ID = 72, + /// OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, Index: clang/include/clang/Sema/DeclSpec.h =================================================================== --- clang/include/clang/Sema/DeclSpec.h +++ clang/include/clang/Sema/DeclSpec.h @@ -281,6 +281,7 @@ static const TST TST_int128 = clang::TST_int128; static const TST TST_extint = clang::TST_extint; static const TST TST_half = clang::TST_half; + static const TST TST_BFloat16 = clang::TST_BFloat16; static const TST TST_float = clang::TST_float; static const TST TST_double = clang::TST_double; static const TST TST_float16 = clang::TST_Float16; Index: clang/include/clang/Basic/TokenKinds.def =================================================================== --- clang/include/clang/Basic/TokenKinds.def +++ clang/include/clang/Basic/TokenKinds.def @@ -590,6 +590,7 @@ // ARM NEON extensions. ALIAS("__fp16", half , KEYALL) +KEYWORD(__bf16 , KEYALL) // OpenCL Extension. KEYWORD(half , HALFSUPPORT) Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -59,6 +59,7 @@ unsigned char BoolWidth, BoolAlign; unsigned char IntWidth, IntAlign; unsigned char HalfWidth, HalfAlign; + unsigned char BFloat16Width, BFloat16Align; unsigned char FloatWidth, FloatAlign; unsigned char DoubleWidth, DoubleAlign; unsigned char LongDoubleWidth, LongDoubleAlign, Float128Align; @@ -100,8 +101,8 @@ unsigned short MaxVectorAlign; unsigned short MaxTLSAlign; - const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat, - *LongDoubleFormat, *Float128Format; + const llvm::fltSemantics *HalfFormat, *BFloat16Format, *FloatFormat, + *DoubleFormat, *LongDoubleFormat, *Float128Format; ///===---- Target Data Type Query Methods -------------------------------===// enum IntType { @@ -188,6 +189,7 @@ // LLVM IR type. bool HasFloat128; bool HasFloat16; + bool HasBFloat16; unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth; unsigned short SimdDefaultAlign; @@ -562,6 +564,9 @@ /// Determine whether the _Float16 type is supported on this target. virtual bool hasFloat16Type() const { return HasFloat16; } + /// Determine whether the _BFloat16 type is supported on this target. + virtual bool hasBFloat16Type() const { return HasBFloat16; } + /// Return the alignment that is suitable for storing any /// object with a fundamental alignment requirement. unsigned getSuitableAlign() const { return SuitableAlign; } @@ -610,6 +615,11 @@ unsigned getFloatAlign() const { return FloatAlign; } const llvm::fltSemantics &getFloatFormat() const { return *FloatFormat; } + /// getBFloat16Width/Align/Format - Return the size/align/format of '__bf16'. + unsigned getBFloat16Width() const { return BFloat16Width; } + unsigned getBFloat16Align() const { return BFloat16Align; } + const llvm::fltSemantics &getBFloat16Format() const { return *BFloat16Format; } + /// getDoubleWidth/Align/Format - Return the size/align/format of 'double'. unsigned getDoubleWidth() const { return DoubleWidth; } unsigned getDoubleAlign() const { return DoubleAlign; } @@ -637,6 +647,11 @@ /// Return the mangled code of __float128. virtual const char *getFloat128Mangling() const { return "g"; } + /// Return the mangled code of bfloat. + virtual const char *getBFloat16Mangling() const { + llvm_unreachable("bfloat not implemented on this target"); + } + /// Return the value for the C99 FLT_EVAL_METHOD macro. virtual unsigned getFloatEvalMethod() const { return 0; } Index: clang/include/clang/Basic/TargetBuiltins.h =================================================================== --- clang/include/clang/Basic/TargetBuiltins.h +++ clang/include/clang/Basic/TargetBuiltins.h @@ -141,7 +141,8 @@ Poly128, Float16, Float32, - Float64 + Float64, + BFloat16 }; NeonTypeFlags(unsigned F) : Flags(F) {} Index: clang/include/clang/Basic/Specifiers.h =================================================================== --- clang/include/clang/Basic/Specifiers.h +++ clang/include/clang/Basic/Specifiers.h @@ -72,6 +72,7 @@ TST_Float16, // C11 extension ISO/IEC TS 18661-3 TST_Accum, // ISO/IEC JTC1 SC22 WG14 N1169 Extension TST_Fract, + TST_BFloat16, TST_float, TST_double, TST_float128, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8088,6 +8088,8 @@ InGroup<BadFunctionCast>, DefaultIgnore; def err_cast_pointer_to_non_pointer_int : Error< "pointer cannot be cast to type %0">; +def err_cast_to_bfloat : Error<"cannot type-cast to __bf16">; +def err_cast_from_bfloat : Error<"cannot type-cast from __bf16">; def err_typecheck_expect_scalar_operand : Error< "operand of type %0 where arithmetic or pointer type is required">; def err_typecheck_cond_incompatible_operands : Error< Index: clang/include/clang/AST/Type.h =================================================================== --- clang/include/clang/AST/Type.h +++ clang/include/clang/AST/Type.h @@ -1979,6 +1979,7 @@ bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 + bool isBFloat16Type() const; // ARM BFloat bool isFloat128Type() const; bool isRealType() const; // C99 6.2.5p17 (real floating + integer) bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) @@ -6783,6 +6784,10 @@ return isSpecificBuiltinType(BuiltinType::Float16); } +inline bool Type::isBFloat16Type() const { + return isSpecificBuiltinType(BuiltinType::BFloat16); +} + inline bool Type::isFloat128Type() const { return isSpecificBuiltinType(BuiltinType::Float128); } Index: clang/include/clang/AST/BuiltinTypes.def =================================================================== --- clang/include/clang/AST/BuiltinTypes.def +++ clang/include/clang/AST/BuiltinTypes.def @@ -212,6 +212,9 @@ // '_Float16' FLOATING_TYPE(Float16, HalfTy) +// '__bf16' +FLOATING_TYPE(BFloat16, BFloat16Ty) + // '__float128' FLOATING_TYPE(Float128, Float128Ty) Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -962,6 +962,7 @@ CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy, SatUnsignedLongFractTy; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON + CanQualType BFloat16Ty; // ARM NEON CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType Float128ComplexTy; Index: clang/include/clang-c/Index.h =================================================================== --- clang/include/clang-c/Index.h +++ clang/include/clang-c/Index.h @@ -3249,6 +3249,7 @@ CXType_UShortAccum = 36, CXType_UAccum = 37, CXType_ULongAccum = 38, + CXType_BFloat16 = 39, CXType_FirstBuiltin = CXType_Void, CXType_LastBuiltin = CXType_ULongAccum, Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -514,8 +514,8 @@ Half-Precision Floating Point ============================= -Clang supports two half-precision (16-bit) floating point types: ``__fp16`` and -``_Float16``. These types are supported in all language modes. +Clang supports three half-precision (16-bit) floating point types: ``__fp16``, +``_Float16`` and ``__bf16``. These types are supported in all language modes. ``__fp16`` is supported on every target, as it is purely a storage format; see below. ``_Float16`` is currently only supported on the following targets, with further @@ -527,6 +527,10 @@ ``_Float16`` will be supported on more targets as they define ABIs for it. +``__bf16`` is purely a storage format; it is currently only supported on the following targets: +* 32-bit ARM +* 64-bit ARM (AArch64) + ``__fp16`` is a storage and interchange format only. This means that values of ``__fp16`` are immediately promoted to (at least) ``float`` when used in arithmetic operations, so that e.g. the result of adding two ``__fp16`` values has type ``float``.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits