diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -325,6 +325,8 @@ builtins (corresponding to the specific names listed in the attribute) in the body of the function the attribute is on. +- Added half float to types that can be represented by ``__attribute__((mode(XX)))``. + Windows Support --------------- diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -52,11 +52,13 @@ enum class FloatModeKind { NoFloat = 255, - Float = 0, + Half = 0, + Float, Double, LongDouble, Float128, - Ibm128 + Ibm128, + Last = Ibm128 }; /// Fields controlling how types are laid out in memory; these may need to @@ -218,7 +220,7 @@ mutable VersionTuple PlatformMinVersion; unsigned HasAlignMac68kSupport : 1; - unsigned RealTypeUsesObjCFPRet : 3; + unsigned RealTypeUsesObjCFPRetMask : (int)FloatModeKind::Last + 1; unsigned ComplexLongDoubleUsesFP2Ret : 1; unsigned HasBuiltinMSVaList : 1; @@ -880,7 +882,9 @@ /// Check whether the given real type should use the "fpret" flavor of /// Objective-C message passing on this target. bool useObjCFPRetForRealType(FloatModeKind T) const { - return RealTypeUsesObjCFPRet & (1 << (int)T); + assert(T <= FloatModeKind::Last && + "T value is larger than RealTypeUsesObjCFPRetMask can handle"); + return RealTypeUsesObjCFPRetMask & (1 << (int)T); } /// Check whether _Complex long double should use the "fp2ret" flavor diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -11742,6 +11742,8 @@ FloatModeKind Ty = getTargetInfo().getRealTypeByWidth(DestWidth, ExplicitType); switch (Ty) { + case FloatModeKind::Half: + return HalfTy; case FloatModeKind::Float: return FloatTy; case FloatModeKind::Double: diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -131,7 +131,7 @@ ARMCDECoprocMask = 0; // Default to no types using fpret. - RealTypeUsesObjCFPRet = 0; + RealTypeUsesObjCFPRetMask = 0; // Default to not using fp2ret for __Complex long double ComplexLongDoubleUsesFP2Ret = false; @@ -284,6 +284,8 @@ FloatModeKind TargetInfo::getRealTypeByWidth(unsigned BitWidth, FloatModeKind ExplicitType) const { + if (getHalfWidth() == BitWidth) + return FloatModeKind::Half; if (getFloatWidth() == BitWidth) return FloatModeKind::Float; if (getDoubleWidth() == BitWidth) diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -418,7 +418,7 @@ RegParmMax = 3; // Use fpret for all types. - RealTypeUsesObjCFPRet = + RealTypeUsesObjCFPRetMask = ((1 << (int)FloatModeKind::Float) | (1 << (int)FloatModeKind::Double) | (1 << (int)FloatModeKind::LongDouble)); @@ -699,7 +699,7 @@ "64-i64:64-f80:128-n8:16:32:64-S128"); // Use fpret only for long double. - RealTypeUsesObjCFPRet = (1 << (int)FloatModeKind::LongDouble); + RealTypeUsesObjCFPRetMask = (1 << (int)FloatModeKind::LongDouble); // Use fp2ret for _Complex long double. ComplexLongDoubleUsesFP2Ret = true; diff --git a/clang/test/CodeGen/aarch64-attr-mode-complex.c b/clang/test/CodeGen/aarch64-attr-mode-complex.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aarch64-attr-mode-complex.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -emit-llvm %s -o - | FileCheck %s + +typedef _Complex float c16a __attribute((mode(HC))); +typedef _Complex double c16b __attribute((mode(HC))); +typedef _Complex float c32a __attribute((mode(SC))); +typedef _Complex double c32b __attribute((mode(SC))); +typedef _Complex float c64a __attribute((mode(DC))); +typedef _Complex double c64b __attribute((mode(DC))); + +// CHECK: define{{.*}} { half, half } @c16_test([2 x half] noundef {{.*}} +// CHECK: ret { half, half } {{.*}} +c16b c16_test(c16a x) { + return x + x; +} + +// CHECK: define{{.*}} { float, float } @c32_test([2 x float] noundef {{.*}}) +// CHECK: ret { float, float } {{.*}} +c32b c32_test(c32a x) { + return x + x; +} + +// CHECK: define{{.*}} { double, double } @c64_test([2 x double] noundef {{.*}}) +// CHECK: ret { double, double } {{.*}} +c64b c64_test(c64a x) { + return x + x; +} diff --git a/clang/test/CodeGen/aarch64-attr-mode-float.c b/clang/test/CodeGen/aarch64-attr-mode-float.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aarch64-attr-mode-float.c @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -emit-llvm %s -o - | FileCheck %s + +typedef float f16a __attribute((mode(HF))); +typedef double f16b __attribute((mode(HF))); +typedef float f32a __attribute((mode(SF))); +typedef double f32b __attribute((mode(SF))); +typedef float f64a __attribute((mode(DF))); +typedef double f64b __attribute((mode(DF))); +f16b tmp; + +// CHECK: define{{.*}} ptr @f16_test(ptr noundef {{.*}}) +// CHECK: store half {{.*}}, ptr @tmp, align 2 +// CHECK: ret ptr @tmp +f16b *f16_test(f16a *x) { + tmp = *x + *x; + return &tmp; +} + +// CHECK: define{{.*}} float @f32_test(float noundef {{.*}}) +// CHECK: ret float {{.*}} +f32b f32_test(f32a x) { + return x + x; +} + +// CHECK: define{{.*}} double @f64_test(double noundef {{.*}}) +// CHECK: ret double {{.*}} +f64b f64_test(f64a x) { + return x + x; +} diff --git a/clang/test/Sema/attr-mode-vector-types.c b/clang/test/Sema/attr-mode-vector-types.c --- a/clang/test/Sema/attr-mode-vector-types.c +++ b/clang/test/Sema/attr-mode-vector-types.c @@ -22,8 +22,7 @@ // expected-error@-1{{unsupported machine mode 'QC'}} // expected-error@-2{{type of machine mode does not match type of base type}} typedef _Complex float __attribute__((mode(HC))) __attribute__((vector_size(256))) vec_t9; -// expected-error@-1{{unsupported machine mode 'HC'}} -// expected-error@-2{{invalid vector element type '_Complex float'}} +// expected-error@-1{{invalid vector element type '_Complex float'}} typedef int __attribute__((mode(SC))) __attribute__((vector_size(256))) vec_t10; // expected-error@-1{{type of machine mode does not match type of base type}} // expected-error@-2{{type of machine mode does not support base vector types}} diff --git a/clang/test/Sema/attr-mode.c b/clang/test/Sema/attr-mode.c --- a/clang/test/Sema/attr-mode.c +++ b/clang/test/Sema/attr-mode.c @@ -37,6 +37,11 @@ __attribute__((mode(QI))) int invalid_func(void) { return 1; } // expected-error{{'mode' attribute only applies to variables, enums, typedefs, and non-static data members}} enum invalid_enum { A1 __attribute__((mode(QI))) }; // expected-error{{'mode' attribute only applies to}} +typedef _Complex float c16a __attribute((mode(HC))); +int c16a_test[sizeof(c16a) == 4 ? 1 : -1]; +typedef _Complex double c16b __attribute((mode(HC))); +int c16b_test[sizeof(c16b) == 4 ? 1 : -1]; + typedef _Complex double c32 __attribute((mode(SC))); int c32_test[sizeof(c32) == 8 ? 1 : -1]; typedef _Complex float c64 __attribute((mode(DC)));