[cfe-commits] RFC: Half floating point support
John McCall
rjmccall at apple.com
Tue Oct 4 16:02:30 PDT 2011
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 0954e20..5364e1a 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1201,9 +1201,22 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_IntegralCast:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
- case CK_FloatingCast:
return EmitScalarConversion(Visit(E), E->getType(), DestTy);
-
+ case CK_FloatingCast: {
+ // Floating casts might be a bit special: if we're doing casts to / from half
+ // FP, we should go via special intrinsics.
+ llvm::Value *V = Visit(E);
+ QualType SrcTy = E->getType();
+
+ if (DestTy->isHalfType()) {
+ V = EmitScalarConversion(V, SrcTy, CGF.getContext().FloatTy);
+ return Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16), V);
+ } else if (SrcTy->isHalfType()) {
+ V = Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16), V);
+ return EmitScalarConversion(V, CGF.getContext().FloatTy, DestTy);
+ } else
+ return EmitScalarConversion(V, SrcTy, DestTy);
+ }
This needs to happen in EmitScalarConversion to get compound assignments working correctly.
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
index a1105d2..19ffcb7 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -185,6 +185,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::ULong:
case BuiltinType::LongLong:
case BuiltinType::ULongLong:
+ case BuiltinType::Half:
case BuiltinType::Float:
case BuiltinType::Double:
case BuiltinType::LongDouble:
The RTTI for 'half' is not, in fact, in the standard library.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index d0a3f6b..a6b5901 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -378,12 +378,19 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// C99 6.3.2.1p2:
// If the lvalue has qualified type, the value has the unqualified
// version of the type of the lvalue; otherwise, the value has the
- // type of the lvalue.
+ // type of the lvalue.
if (T.hasQualifiers())
T = T.getUnqualifiedType();
-
- return Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
- E, 0, VK_RValue));
+
+ ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
+ E, 0, VK_RValue));
+
+ // Half FP is a bit different: it's a storage-only type, meaning that lvalue
+ // to rvalue conversion also yields an implicit cast to float.
+ if (T->isHalfType())
+ return ImpCastExprToType(Res.take(), Context.FloatTy, CK_FloatingCast);
+
+ return Res;
}
I think this should be modeled as a promotion and performed during
UsualUnaryConversions, not during DefaultLvalueConversion.
@@ -8170,6 +8177,12 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
Opc == UO_PostInc,
Opc == UO_PreInc ||
Opc == UO_PreDec);
+ // Half FP is a bit different: it's a storage-only type, meaning that any
+ // "use" of it should involve promotion to float.
+ if (resultType->isHalfType()) {
+ Input = ImpCastExprToType(Input.take(), Context.FloatTy, CK_FloatingCast);
+ resultType = Context.FloatTy;
+ }
As Eli mentioned, this is wrong.
@@ -3910,6 +3910,24 @@ InitializationSequence::InitializationSequence(Sema &S,
}
AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
+ } else if (SourceType->isHalfType() && ICS.isStandard() &&
+ ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
+ // Convert to rvalue doint promotion to float first.
+ ImplicitConversionSequence LvalueICS;
+ LvalueICS.setStandard();
+ LvalueICS.Standard.setAsIdentityConversion();
+ LvalueICS.Standard.setAllToTypes(Context.FloatTy);
+ LvalueICS.Standard.setToType(0, ICS.Standard.getToType(0));
+ LvalueICS.Standard.First = ICS.Standard.First;
+ LvalueICS.Standard.Second = ICK_Floating_Promotion;
+
+ AddConversionSequenceStep(LvalueICS, Context.FloatTy);
+
+ // Now perform any other conversion remaining.
+ ICS.Standard.setFromType(Context.FloatTy);
+ ICS.Standard.First = ICK_Identity;
+ ICS.Standard.setToType(0, Context.FloatTy);
+ AddConversionSequenceStep(ICS, Entity.getType());
This should be modeled in the standard-conversion logic.
+
+ // Half can be promoted to float.
+ if (FromBuiltin->getKind() == BuiltinType::Half &&
+ ToBuiltin->getKind() == BuiltinType::Float)
+ return true;
Half can also be promoted to double.
+ // Half FP is a bit different: it's a storage-only type, meaning that any
+ // "use" of it should involve promotion to float.
+ if (From->getType()->isHalfType())
+ From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).take();
+
This clearly doesn't belong here.
John.
More information about the cfe-commits
mailing list