Adding half float to types that can be represented by __attribute__((mode(xx))).
Original implementation authored by George Steed.
Differential Revision: https://reviews.llvm.org/D126479
- Added the ``clang::annotate_type`` attribute, which can be used to add
annotations to types (see documentation for details).
+- Added half float to types that can be represented by ``__attribute__((mode(XX)))``.
+
Windows Support
---------------
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
mutable VersionTuple PlatformMinVersion;
unsigned HasAlignMac68kSupport : 1;
- unsigned RealTypeUsesObjCFPRet : 3;
+ unsigned RealTypeUsesObjCFPRetMask : (int)FloatModeKind::Last + 1;
unsigned ComplexLongDoubleUsesFP2Ret : 1;
unsigned HasBuiltinMSVaList : 1;
/// 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
FloatModeKind Ty =
getTargetInfo().getRealTypeByWidth(DestWidth, ExplicitType);
switch (Ty) {
+ case FloatModeKind::Half:
+ return HalfTy;
case FloatModeKind::Float:
return FloatTy;
case FloatModeKind::Double:
ARMCDECoprocMask = 0;
// Default to no types using fpret.
- RealTypeUsesObjCFPRet = 0;
+ RealTypeUsesObjCFPRetMask = 0;
// Default to not using fp2ret for __Complex long double
ComplexLongDoubleUsesFP2Ret = false;
FloatModeKind TargetInfo::getRealTypeByWidth(unsigned BitWidth,
FloatModeKind ExplicitType) const {
+ if (getHalfWidth() == BitWidth)
+ return FloatModeKind::Half;
if (getFloatWidth() == BitWidth)
return FloatModeKind::Float;
if (getDoubleWidth() == BitWidth)
RegParmMax = 3;
// Use fpret for all types.
- RealTypeUsesObjCFPRet =
+ RealTypeUsesObjCFPRetMask =
((1 << (int)FloatModeKind::Float) | (1 << (int)FloatModeKind::Double) |
(1 << (int)FloatModeKind::LongDouble));
"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;
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
// 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}}
__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)));